Vue-router导航守卫

130 阅读3分钟

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传递回调的唯一守卫。对于beforeRouteUpdatebeforeRoutLeave来说,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)
  }
}

完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫
  9. 导航被确认
  10. 调用全局的 afterEach 钩子
  11. 触发 DOM 更新
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入