Vue router源码解析(todo)
Vue-router源码解析
status: Draft tags: Vue, 源码解析 Created time: March 7, 2023 10:57 AM emoji: https://vuejs.org/logo.svg
VueRouter类
VueRouter
三种mode
实现导航
一次导航的完整步骤
vue-router一次完整的导航包含以下步骤:
导航被触发。
在失活的组件里调用
beforeRouteLeave守卫。调用全局的
beforeEach守卫。在重用的组件里调用
beforeRouteUpdate守卫 (2.2+)。在路由配置里调用
beforeEnter。解析异步路由组件。
在被激活的组件里调用
beforeRouteEnter。调用全局的
beforeResolve守卫 (2.5+)。导航被确认。
调用全局的
afterEach钩子。触发 DOM 更新。
调用
beforeRouteEnter守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传入。
实现push
前端浏览器跳转页面通常有两种方式,代码跳转和浏览器跳转,代码跳转包含调用this.$router.push() 和点击<router-link>组件,浏览器跳转则是点击浏览器特定按钮,例如前进和后退按钮进行跳转。
无论是代码跳转还是浏览器跳转,其最终都调用了transitionTo函数,下面以HTML5History模式为例。
transitionTo函数
transitionTo位于类History,它是HashHistory、HTML5History 、AbstractHistory的父类。
transitionTo会再调用confirmTransition 函数来确定是否跳转路由,并传递一个onComplete函数作为完成时的回调。
confirmTransition
confirmTransition 函数将所有要执行的函数存储到队列中,以确保执行顺序的正确。最初执行:
runQueue 函数会按顺序将这些守卫函数传入iterator 函数中执行,当用户在导航守卫中调用next()调转其他路由时,又会重新调用push跳转到目标路由。
在confirmTransition函数中调用runQueue时,又传入了一个回调函数,以便queue执行完毕后执行。
在这个函数中又会以相同的方式执行
激活路由的beforeRouteEnter守卫
全局beforeResolve守卫
最后又调用了
这里的onComplete来自transitionTo函数:
updateRoute函数执行的过程中会调用this.cb(route) ,这里的cb函数来自前面VueRouter类的init方法中:
由于app._route是响应式的,改变app._route时就会导致页面重新渲染,也就是触发了DOM更新。
也就是说在这一过程中做了:
更新路由
执行用户onComplete函数
确定路由(ensureURL)
执行全局beforeEach守卫
触发 DOM 更新。
为什么app._route = route先执行,但是DOM却在后面才触发更新呢?这是因为Vue组件渲染是异步的,由一个异步调度系统控制。
最后,调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
这里使用nextTick的原因也同样是因为要延迟到DOM更新后再执行。
至此,导航解析核心流程执行完毕:
导航被触发。
在失活的组件里调用
beforeRouteLeave守卫。调用全局的
beforeEach守卫。在重用的组件里调用
beforeRouteUpdate守卫 (2.2+)。在路由配置里调用
beforeEnter。解析异步路由组件。
在被激活的组件里调用
beforeRouteEnter。调用全局的
beforeResolve守卫 (2.5+)。导航被确认。
调用全局的
afterEach钩子。触发 DOM 更新。
调用
beforeRouteEnter守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传入。