Vue-router导航守卫
有的时候,需要通过路由来进行一些操作,比如最常见的登录权限验证,当用户满足条件时,才让其进入导航,否则就取消跳转,并跳到登录页面让其登录。 为此有很多种方法可以植入路由的导航过程:全局的,单个路由独享的,或者组件级的
1. 全局前置守卫
vue-router
全局守卫有如下三个
router-beforeEach
全局前置守卫router-beforeResolve
全局解析守卫router.afterEach
全局后置钩子
具体使用
(1)全局前置守卫:router-beforeEach
,使用比较多的场景是用户未能验证身份时重定向到 /login
const router = new VueRouter({...})
router.beforeEach((to, from, next)=>{
if(to.name !== 'Login' && !isAuthenticated){
next({name: 'Login'})
}else{
next()
}
})
守卫可以接收三个参数
to
:即将要进入的目标路由对象
from
:当前导航正要离开的路由next
:理解放行,next('/')
或者next({ path: '/' })
: 跳转到一个不同的地址
(2)全局解析守卫router-beforeResolve
和 router.beforeEach
类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
router.beforeResolve((to,from,next)=>{
next();
})
(3)全局后置钩子router.afterEach
和守卫不同的是,这些钩子不会接受 next
函数也不会改变导航本身,例如现在跳转之后滚动条需要回到顶部
router.afterEach((to, from) => {
window.scrollTo(0, 0)
})
2.路由独享守卫
beforeEnter
如果你不想配置全局路由守卫,可以单独为某些路由配置守卫,同样也能接收到三个参数to
,from
,next
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
console.log('即将进入Foo页面')
next()
}
}
]
})
3.组件内守卫
最后,以下的路由导航守卫可以直接在组件内定义
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
同样也能接收到三个参数to
,from
,next
,下面对组件内守卫逐个介绍
beforeRouteEnter
守卫不能访问到this
,因为在进入组件之前就已经触发了,也就是新的组件还没有被创建。
不过可以通过传一个回调给next
来访组件实例。这个回调会在导航被确认的时候执行,并且把组件实例作为回调方法的参数。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
注意:beforeRouteEnter
是支持给next
传递回调的唯一守卫。对于beforeRouteUpdate
和beforeRoutLeave
来说,this
已经可用了,所以不支持传递回调,因为没有必要了。
beforeRouteUpdate
beforeRouteUpdate(to, from, next){
this.name = to.params.name
next()
}
有的时候用户还没有保存修改就突然离开了,这时候需要提示一下用户,beforeRouteLeave
这个守卫就可以实现这个功能
beforeRouteLeave(to, from, next){
const answer = window.confirm('你真的想离开吗?您有未保存的更改!')
if(answer){
next()
}else{
next(false)
}
}
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 - 在路由配置里调用
beforeEnter
- 解析异步路由组件
- 在被激活的组件里调用
beforeRouteEnter
- 调用全局的
beforeResolve
守卫 - 导航被确认
- 调用全局的
afterEach
钩子 - 触发 DOM 更新
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入