vue-router hooks实现原理
首先分析一下hook实际就是回调函数,然后在特定的时机,按照顺序依次执行,并且可以中断路由的跳转
hooks种类
- 路由实例上的hooks包括beforeEach、beforeResolve
- 路由配置文件也就是routes包括beforeEnter
- 销毁vue实例里的beforeRouteLeave
- 更新状态的vue的beforeRouteUpdate
- 新实例化的vue的beforeRouteEnter
hooks执行顺序
- beforeRouteLeave(当有嵌套时,子组件的hook优先于父组件执行)
- beforeEach(有多个时,按照注册顺序先后执行,注册完后会返回取消注册的函数)
- beforeRouteUpdate(当有嵌套时,父组件的hook优先于子组件执行)
- beforeEnter
- 异步组件的解析
- beforeRouteEnter
- beforeResolve
hooks原理
采用高阶函数加队列的方式,按照顺序依次执行。具体的实现如下:
hool1、hook2、hook3依次调用,并且要往下执行必须要调用next
let list = []
const hook1 = (to,from,next) => {
console.log('我是hook1')
// 实现路由拦截效果,不满足条件就不做路由跳转
next()
}
const hook2 = (to,from,next) => {
console.log('我是hook2')
// 未登录,路由重定向到login
next()
}
const hook3 = (to,from,next) => {
console.log('我是hook3')
// 未登录,路由重定向到login
next()
}
// 这里简单实现hooks的队列,源码里面也是如此,只是不同类别的hook分开存储
// 组件内部的hooks是通过Vue.extend构造出子类,从子类中的options中取得
list.push(hook1,hook2,hook3)
// 所有的hook执行完毕以后,跳转路由的回调函数
const cb = () => {
// 跳转路由
}
// hook遍历器,调用next即可接着调用下一个hook
const iterator = (hook,next) => {
// 源码中能够取得to和from,这里就简单模拟一下
let to = {path:'/about'}
let from = {path:'/home'}
hook(to,from,(to) => {
// 根据hook里面用户传递过来的参数,判断
if(to === false) {
console.log('终止跳转')
} else if(typeof to === 'string' || (typeof to === 'object' && to.path)) {
// 跳转到新的路由
} else {
// 执行其余的hooks
next(to)
}
})
}
// 用来执行hook的队列函数
function runQueue(queue, fn, cb) {
const step = index => {
if (index >= queue.length) {
cb()
} else {
if (queue[index]) {
fn(queue[index], () => {
step(++index)
})
} else {
step(++index)
}
}
}
step(0)
}
runQueue(list,iterator,cb)