vue2的路由守卫(钩子函数),路由死循环怎么解决?

我们需要通过路由来进行一些操作,比如最常见的登录权限验证,当用户满足条件时,才让其进入导航,否则就取消跳转,并跳到登录页面让其登录。

全局守卫

vue-router全局有三个守卫

  1. router.beforeEach 全局前置守卫 进入路由之前
  2. router.beforeResolve 全局解析守卫,在beforeRouteEnter调用之后调用
  3. router.afterEach 全局后置钩子 进入路由之后

使用方法

    // main.js 入口文件
    import router from './router'; // 引入路由
    router.beforeEach((to, from, next) => { 
      next();
    });
    router.beforeResolve((to, from, next) => {
      next();
    });
    router.afterEach((to, from) => {
      console.log('afterEach 全局后置钩子');
    });

to,from,next 这三个参数:

to和from是将要进入和将要离开的路由对象,路由对象指的是平时通过this.$route获取到的路由信息配置对象,比如path传参 this.$route.query接收

next:Function 这个参数是个函数,且必须调用,否则不能进入路由(页面空白)。

  • next() 进入该路由。

  • next(false): 取消进入路由,url地址重置为from路由地址(也就是将要离开的路由地址)。

  • next 跳转新路由,当前的导航被中断,重新开始一个新的导航。

      我们可以这样跳转:next('path地址')或者next({path:''})或者next({name:''})
      且允许设置诸如 replace: true、name: 'home' 之类的选项
      以及你用在router-link或router.push的对象选项。
    

路由独享守卫

如果你不想全局配置守卫的话,你可以为某些路由单独配置守卫,写在路由配置里

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          beforeEnter: (to, from, next) => { 
            // 参数都一样
          }
        }
      ]
    })

路由组件内的守卫:

  1. beforeRouteEnter 进入路由前
  2. beforeRouteUpdate 路由复用同一个组件时
  3. beforeRouteLeave 离开当前路由时

三个钩子函数

  beforeRouteEnter (to, from, next) {
    // 在路由独享守卫后调用 不能获取组件实例 this,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) { 
    // 在当前路由改变,但是该组件被复用时调用 可以访问组件实例 this
    // 可以用来接收动态路由传过来的参数
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用,可以访问组件实例 this
  }

beforeRouteEnter访问this

因为钩子在组件实例还没被创建的时候调用,所以不能获取组件实例 this,可以通过传一个回调给next来访问组件实例

但是回调的执行时机在mounted后面,所以在我看来这里对this的访问意义不太大,可以放在created或者mounted里面。

    beforeRouteEnter (to, from, next) {
    console.log('在路由独享守卫后调用');
      next(vm => {
        // 通过 vm 访问组件实例 this 执行回调的时机在mounted后面,
      })
    }

beforeRouteLeave:

导航离开该组件的对应路由时调用,我们用它来禁止用户离开,比如还未保存草稿或者在用户离开前,将setInterval销毁,防止离开之后,定时器还在调用

    beforeRouteLeave (to, from , next) {
      if (文章保存) {
        next(); // 允许离开或者可以跳到别的路由 上面讲过了
      } else {
        next(false); // 取消离开
      }
    }

关于钩子的一些知识:

路由钩子函数的错误捕获

如果我们在全局守卫/路由独享守卫/组件路由守卫的钩子函数中有错误,可以这样捕获:

    router.onError(callback => { 
    // 2.4.0新增 并不常用,了解一下就可以了 
      console.log(callback, 'callback');
    });

跳转死循环解决

    {
     path: '/login',
     name: 'login',
     component: () => import('../views/login.vue'),
     meta: {
       intercept: true
     }
    }
router.beforeEach((to, from, next) => {
  let token = localStorage.getItem('token')
  console.log(to.meta.intercept);
  if (token && token != null) { // 本地有 token 去下一步
    next()
  } else { // 不是 login 页面我再去跳 ,是 login 就会死循环,因为login 也是页面就会被守卫
    if (to.meta.intercept && to.path != '/login') {
      // 路由原信息为true 并且 不是 login 页面 去login 防止死循环
      next('/login')
    } else {
      next()  // vue3 从 next 换成了 return 执行下一步
    }
  }
})

全局后置钩子的跳转:

文档中提到因为router.afterEach不接受next函数所以也不会改变导航本身,意思就是只能当成一个钩子来使用,但是我自己在试的时候发现,我们可以通过这种形式来实现跳转:

    // main.js 入口文件
    import router from './router'; // 引入路由
    router.afterEach((to, from) => {
      if (未登录 && to.path !== 'login') {
        router.push({ path: 'login' }); // 跳转login
      }
    });

s-z-h

猜你喜欢

转载自blog.csdn.net/qq_54753561/article/details/122352723
今日推荐