Vue+TypeScript+ElementUI 实战 (三)路由守卫

457 阅读3分钟

1、什么是路由守卫?

路由守卫又称导航守卫,指是 路由跳转前、中、后过程中的一些钩子函数 。官方解释是vue-router提供的导航守卫,要通过跳转或取消的方式来守卫导航。路由守卫分为三种,全局路由、组件内路由,路由独享

2、路由的分类

2.1 全局路由守卫

router.beforeEach((to, form, next) => {
  // 路由跳转前触发
  console.log('全局前置守卫 beforeEach')
  next()
})
router.beforeResolve((to, form, next) => {
  // 在所有组件内守卫和异步路由组件被解析之后触发
  console.log('全局解析守卫 beforeResolve')
  next()
})
router.afterEach((to, form) => {
 //  路由跳转完成后触发
  console.log('全局后置守卫 afterEach')
})

使用场景:

  • 全局前置守卫:用于登录时验证token是否有效、开启页面加载进度条
  • 全局解析守卫:
  • 全局后置守卫:关闭进度条

2.2 路由独享守卫

{
    path: '/list',
    name: 'list',
    alias: '/aaa',
    component: () => import('@views/List'),
    children: [
      {
        path: ':id',
        name: 'details',
        component: () => import('@views/Details'),
        props: true,
        beforeEnter: (to, from, next) => {
           // 单个路由配置 ,单个路由进入前触发
          console.log('路由独享守卫 beforeEnter')
          next()
        }
      }
    ]
  }

使用场景:进入当前路由前要干什么事就在这里处理

2.3 组件路由守卫

beforeRouteEnter(to, from, next) {
    // 在组件生命周期beforeCreate阶段触发
    console.log('组件内路由前置守卫 beforeRouteEnter', this) // 访问不到this
    next((vm) => {
      console.log('组件内路由前置守卫 vm', vm) // vm 就是this
    })
  },
  beforeRouteUpdate(to, from, next) {
    // 当前路由改变时触发
    console.log('组件内路由更新守卫 beforeRouteUpdate')
    next()
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时触发
    console.log('组件内路由离开守卫 beforeRouteLeave', this)
    next()
  }

2.4 参数说明

  • to: 即将要进入的路由对象

  • from: 即将要离开的路由对象,

  • next(): 这个参数是个函数,且必须调用,否则不能进入路由(空白页面),执行的效果由next函数中的参数决定,它的参数有以下4种情况

    • next():没有参数,表示可以进入到to的路由中
    • next(false):参数为一个布尔值false,中断当前的导航,回到from路由
    • next('/') 或 next({ path: '/' }):参数为一个路径,相当于执行了this.$router.push('/')
    • next(error):参数为error,中断当前导航,将该错误传递给router.onError()注册过的回调

注意: 必须要确保 next函数 在任何给定的导航守卫中都被调用过一次。它可以出现多次,但是只能在所有的逻辑路径都不重叠的情况下,否则会报错。

错误案例:

router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  // 如果用户未能验证身份,则 `next` 会被调用两次
  next()
})

正确案例:

router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})

3、路由的执行顺序

在这里插入图片描述 全局前置守卫 beforeEach 路由独享守卫 beforeEnter 组件内路由前置守卫 beforeRouteEnter 全局解析守卫 beforeResolve 全局后置守卫 afterEach 组件生命周期:创建前 beforeCreate 组件生命周期:创建后 created 组件生命周期:挂载前 beforeMount 组件内路由前置守卫 beforeRouteEnter 的 next 回调 组件生命周期:挂载后 mounted