经过上一节分析我们知道,vueRouter在初始化的最后一步执行了transitionTo进行路由过渡
这一节我们将尝试分析,路由过渡过程中都做了哪些事情
该函数的入参为history.getCurrentLocation的返回值、
函数
history.getCurrentLocation在history和hash模式下对应的引用不同
history下
即
通过location对象的pathname属性获取当前浏览器的url地址,如vue官网地址为https://cn.vuejs.org/v2/guide/components-slots.html,则得到的path为/v2/guide/components-slots.html
base是再路由中配置的,这在history模式中解决刷新404时有用,当前未作配置,跳过
最后通过window.location.search获取?后的文本url,如http://www.baidu.com?aaa=1,则匹配到?aaa=1;通过window.location.hash取到我们的hast值,如http://www.baidu.com?aaa=1#head,则匹配#head。那么最终返回的值为http://www.baidu.com?aaa=1#head
hash下
即
通过window.location.href拿到路径,对应history的结果,一样为http://www.baidu.com?aaa=1#head
最后将hash值截取掉,即http://www.baidu.com?aaa=1
也就是说,不论哪种模式,返回是http://www.baidu.com?aaa=1
setupListeners函数
这在执行时将回调history.setupListeners函数
history下
通过对popstate的监听以观测url的变化,将触发回调handleRoutingEvent,重新执行过渡
hash下
通过对hashchange的监听以观测url的变化,将触发回调handleRoutingEvent,重新执行过渡
也就是说,不论是history还是hash模式都将最终执行到this.transitionTo函数,入参为当前页面url地址、回调函数、undefined
首先通过router.match拿到route定义,即调用vueRouter的match函数,入参为url地址、当前的record对象,undefined
即
即
因此,在路由过渡之前,将生成一个当前路径的路由对象
回到this.transitionTo,调用confirmTransition,传入路由对象(将要激活的路由)
框红一的位置,拿到我们当前正在激活和路由和上一次的路由
框红二的位置,对新旧路由进行比对,如果是同一个,则调用ensureURL,这最终将调用history.pushState,修改hisotry对象和地址栏,但是页面内容不改变,也不会触发popstate事件
框红三的位置
首先调用resolveQueue,传入当前和上一次的路由对象中保存的metched,这实际上指向的是在路由映射表中保存的record,假设本次操作是从/foo——>/info
则current为
next为
resolveQueue函数
通过Math.max取最大值,然后遍历找不相等。当由一个一级路由跳转到二级子路由的时候,实际上next会有两个,比如从/info跳转到/info/child时,此时next为['/info的record','/info/child的record'],我们需要通过遍历找出不相等的哪一个,即跳过/foo
那么返回的updated则标识上一次旧路由,即/info;activated标识新路由,即/foo/child,deactivated则标识失效的路由,显然只要i有值,则标识null
返回的框红三的位置
定义queue,这是一个一维数组,这里保存着所有的导航钩子,如beforeEach、afterEach、beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
定义iterator迭代器
可以看出,这里实际上对应的就是我们的导航守卫,将在runQueue时被执行(也就是说该方法是用来跑我们在路由中配置的守卫用的)
框红的onComplete为
调用updateRoute将当前正则激活的路由更新为当前路由;再次执行一次setupListeners对当前url进行监听,因为旧路由对应的组件被销毁时,popstate或hashchange也被相应的移除
因此,路由过渡的核心是通过监听popstate或hashchange事件回调执行transitionTo,并在transitionTo过程中完成钩子函数的调用(runQueue)及浏览器历史记录的修正(pushState),以达到视图的更新