0
点赞
收藏
分享

微信扫一扫

Vue--Router--各个版本的事件监听



简介

        本文介绍Vue-router各个版本的事件监听的区别。

问题引出

        在学习vueRouter源码时发现,路由变化的监听是通过popstate或者hashchange来监听路由变化的。但在使用中发现,不同版本处理的效果不一致,比如:在3.1.6版本通过push等方法更新路由的时候,不会触发hash中路由监听事件;但是在3.0.3版本中,是会触发的路由监听事件的。

        那么,导致这些的原因到底是什么呢?首先我们来分析下两种事件监听的特点

popstate事件

        调用history.pushState()或history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back()。


hashchange事件

只要锚点也就是hash值有更新,就会触发hashchange监听事件。


了解了两种路由监听事件的特点后,再去分析源码就简易多了。

源码分析

概述

更新路由的方法:浏览器判断是否支持pushstate方法。

  1. 若支持:调用pushstate、replacestate等方法更新路由;
  2. 若不支持:使用window.location.hash去更新。

监听路由变化的方法:浏览器判断是否支持pushstate方法。

  1. 若支持:监听popstate事件;
  2. 若不支持:监听hashchange事件。

vue-router3.1.6

var supportsPushState =
inBrowser &&
(function () {
var ua = window.navigator.userAgent;

if (
(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
ua.indexOf('Mobile Safari') !== -1 &&
ua.indexOf('Chrome') === -1 &&
ua.indexOf('Windows Phone') === -1
) {
return false
}
// 谷歌浏览器return true
return window.history && 'pushState' in window.history
})();


// hash监听方法
// 若支持pushstate,则监听popstate,否则监听hashchange
window.addEventListener(
supportsPushState ? 'popstate' : 'hashchange',
function () {
var current = this$1.current;
if (!ensureSlash()) {
return
}
this$1.transitionTo(getHash(), function (route) {
if (supportsScroll) {
handleScroll(this$1.router, route, current, true);
}
if (!supportsPushState) {
replaceHash(route.fullPath);
}
});
}
);

// 更新路由方法
// 若支持pushstate则调用history.pushstate,否则调用window.location更新路由
function pushHash(path) {
if (supportsPushState) {
pushState(getUrl(path));
} else {
window.location.hash = path;
}
}

vue-router3.0.3

其他部分一样,只看supportsPushState方法:

var supportsPushState = inBrowser && (function () {
var ua = window.navigator.userAgent;

// 与316版本相比多出来的判断。谷歌浏览器访问return false,即不支持pushstate方法
if (ua.indexOf('Chrome') !== -1) {
return false
}

if (
(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
ua.indexOf('Mobile Safari') !== -1 &&
ua.indexOf('Chrome') === -1 &&
ua.indexOf('Windows Phone') === -1
) {
return false
}

return window.history && 'pushState' in window.history
})();

原因总结

vue-router3.1.6

  • 谷歌浏览器支持pushstate(supportsPushState值为true)
  • pushHash最终调用的是pushState
  • 路由监听的事件是popstate
  • popstate不会触发popstate事件监听

        路由变化不会触发事件监听,所以调用push方法只触发一次transitionTo方法,只更新一次视图。

vue-router3.0.3

  • 谷歌浏览器不支持pushstate(supportsPushState值为false)
  • pushHash最终调用的是window.location.hash
  • 路由监听的事件是hashchange
  • pushHash最后调用的window.location.hash方法触发了hashchange监听的事件

        此时路由变化就会触发事件监听,所以我们调用push方法会触发两次transitionTo方法,但是由于我们在confirmTransition中有相同路径就不继续往下走的拦截,所以,最后只会更新一次视图。

其他网址

​​https://www.jianshu.com/p/073c3826541b​​

举报

相关推荐

0 条评论