在实现路由跳转之前往往需要有一定的判断和操作在跳转,这时就可以用到导航守卫
注意:参数或查询的改变并不会触发进入/离开的导航守卫,可以通过观察$route对象应对这些变化,或使用beforeRouteUpdate的组件来守卫
router.beforeEach
// 在路由配置文件中注册一个全局前置守卫(router.beforeEach)函数
router.beforeEach(( to , from , next )=>{
// to : 将要跳转的目标路由
// from : 当前正要跳转的路由
// next : function:一定要调用该方法来resolve这个钩子,执行结果依赖于next的参数
/*
next() : 放行,进入目标路由
next(false) : 不放行,终端当前导航
next('/')或next({path:'/'}) : 跳转到一个不同的地址
next(error) : 如果传入next的参数是一个error实例,导航会被终止且该错误会被传递给
router.onError()注册过的回调
*/
})
注:守卫是异步解析执行,当一个导航触发时,全局前置守卫按顺序执行,此时守卫在所有守卫reslove完之前一直处于等待中
确保next函数在任何给定的导航守卫中都被严格调用一次。他可以出现多于一次,但是只能是在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错
可以在路由配置上直接定义 beforeEnter 守卫
// 路由配置文件
const router = new VueRouter({
routes:[
{
path : '/home',
component : Home ,
beforeEnter : ( to, from, next )=>{
// ......
// 这些守卫同全局前置守卫方法参数一样
}
}
]
})
可以在路由组件内直接定义一下路由导航守卫
beforeRouterEnter、beforeRouterUpdate(2.2新增)、beforeRouterLeave
// 在路由组件内直接定义
beforeRouteEnter(to, from, next){
// 在渲染该组件对应路由被confirm前调用
// 不!能!获取组件实例对象 'this'
// 因为这个守卫执行前,组件实例还未被创建
},
beforeRouteUpdate(to, from, next){
// 当前路由改变,但该组件被复用时调用,也就是对于带动态参数的路由,路由不变参数改变时调用
// 可以获取组件实例对象 'this'
},
beforeRouteLeave(to, from, next){
// 导航离开该组件的对应路由时调用
// 可以获取组件实例对象 'this'
}
问题:beforeEnter守卫不能访问this,如果就想访问组件实例该怎么办呢?
解决:可以给next传一个回调函数来访问组件实例,在导航被确认的时候执行回调,将组件实例作为回调的参数
beforeRouteEnter(to,from,next){
next(vm=>{ // 通过‘vm’访问组件实例 })
}
注意:beforeRouteEnter是支持给next传递回调的唯一守卫,对应其他两个this已经可以用了,所以不支持回调,因为没有必要了。
2.5.0新增
在 2.5.0+ 你可以用 router.beforeResolve
注册一个全局守卫。这和 router.beforeEach
类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next
函数也不会改变导航本身:
router.afterEach((to, from) => {
// ...
})
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。- 调用全局的
beforeEach
守卫。- 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。- 在路由配置里调用
beforeEnter
。- 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。- 调用全局的
beforeResolve
守卫 (2.5+)。- 导航被确认。
- 调用全局的
afterEach
钩子。- 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。