vue-router提供了导航守卫,在路由跳转过程中来对导航进行处理,导航氛围三个级别:全局的、单个路由独享的、组件级的。
动态参数或者参数参数的改变并不会触发进入/离开的守卫,可以watch
监听$route
对象或者在beforeRouteUpdate
函数中进行处理
router.beforeEach
注册全局前置守卫:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
守卫是异步执行,导航跳转过程在所有守卫resolve之前一直处于等待中。
beforeEach
接受三个参数,第一个参数to
是将要进入的目标的路由对象,第二个参数from
是当前导航要离开的路由对象,第三个参数next
是一个函数,必须通过执行这个函数来确定导航的状态
// 继续向下执行(执行钩子,如果钩子执行完毕确认导航)
next();
// 中断导航
next(false);
// 跳转到不同的地址
next('/');
next({ path: '/'});
// 抛出 Error 实例给 router.onError 回调,终止导航,
next(new Error('error'))
router.beforeResolve
也可以注册全局守卫,与router.beforeEach
类似,区别是在导航被确认前,且组件内所有守卫和异步组件被解析后执行
router.beforeResolve((to, from, next) => {});
router.afterEach
是全局后置钩子,它不会接受next
函数,也不会改变导航本身
路由配置上定义beforeEnter
守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
它与全局守卫的参数一致,只是会在特定的路由起作用
组件内可以定义进入、离开、更新三中守卫
在组件内定义beforeRouterEnter
,会在导航被确认前调用,这时候组件实例还没有创建,所以不能获取到组件实例this
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {},
}
可以为next
传一个回调来访问组件实例,在导航被确认时执行,这个回调的参数就是组件实例:
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
注意,beforeRouterEnter
是支持给next
传递回调的唯一的守卫。
在组件内定义beforeRouterLeave
,会在导航离开组件的对应路由前调用,可以访问组件实例this
const Foo = {
template: `...`,
beforeRouteLeave (to, from, next) {},
}
这个守卫一般用next(false)
来禁止在用户在还未保存修改前突然离开
在组件内定义beforeRouterUpdate
,在路由发生改变,组件被复用时会调用
例如动态路由/user/:id
的参数id
改变时,从/user/1
跳转到/user/2
时,会访问同一个组件,组件实例会被复用,此时其他导航守卫都不会被调用,只会触发beforeRouterUpdate
这个守卫
const Foo = {
template: `...`,
beforeRouteUpdate (to, from, next) {},
}
各种导航解析时,会先从组件离开导航开始执行,然后执行前置→解析→后置,而各种前置导航是从全局到局部的,全局→路由→组件
路由执行
next
后的顺序与Koa的中间件的原理类似,都是洋葱圈模型,一层层进入后直到afterEach
在按照原来的进入的相反顺序离开。
// 组件离开
beforeRouteLeave start
// 全局前置
beforeEach start
// 路由独享前置
beforeEnter start
// 组件前置
beforeRouteEnter start
// 全局解析
beforeResolve start
// 全局后置
afterEach
beforeResolve end
beforeRouteEnter end
beforeEnter end
beforeEach end
beforeRouteLeave end
当组件复用时,只会执行全局的前置、解析,以及组件本身的更新
beforeEach start
beforeRouteUpdate start
beforeResolve start
afterEach
beforeResolve end
beforeRouteUpdate end
beforeEach end
beforeRouteLeave
beforeEach
beforeRouteUpdate
守卫(注意,只有重用组件才有这一步)beforeEnter
(注意,重用组件不会执行这一步)beforeRouteEnter
(注意,重用组件不会执行这一步)beforeResolve
afterEach
beforeRouteEnter
守卫中传给next
的回调函数。