Vue2's routing guard (hook function), how to solve the routing infinite loop?

We need to perform some operations through routing, such as the most common login permission verification. When the user meets the conditions, let him enter the navigation, otherwise cancel the jump, and jump to the login page to let him log in.

global guard

vue-router has three guards globally :

  1. router.beforeEach before the global front guard enters the route
  2. router.beforeResolve global resolution guard, called after beforeRouteEnter is called
  3. router.afterEach after the global post hook enters the route

How to use :

    // 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 these three parameters:

to and from are the routing objects that will enter and leave. The routing object refers to the routing information configuration object usually obtained through this.$route, such as the path parameter this.$route.query to receive .

The parameter next:Function is a function and must be called, otherwise the route cannot be entered (the page is blank).

  • next() enters the route.

  • next(false): Cancel the incoming route, and the url address is reset to the from route address (that is, the route address to be left).

  • next jumps to a new route, the current navigation is interrupted, and a new navigation is restarted.

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

Routing exclusive guard

If you don't want to configure guards globally, you can configure guards individually for certain routes and write them in the route configuration

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

The guard inside the routing component:

  1. beforeRouteEnter before entering the route
  2. beforeRouteUpdate routing reuses the same component
  3. beforeRouteLeave when leaving the current route

Three hook functions

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

beforeRouteEnter访问this

Because the hook is called when the component instance has not been created, the component instance cannot be obtained, and the component instancethis can be accessed by passing a callback to nextit .

But the execution timing of the callback is after the mounted , so in my opinion , the access to this here is of little significance and can be placed in createdor mountedinside.

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

beforeRouteLeave:

Called when the navigation leaves the corresponding route of the component, we use it to prohibit the user from leaving, for example, the draft has not been saved , or it will be destroyed before the user leaves setInterval, preventing the timer from being called after leaving .

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

Some knowledge about hooks:

Error trapping for route hook functions

If we have an error in the hook function of the global guard/routing exclusive guard/component routing guard, we can catch it like this:

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

Jump infinite loop solution

    {
     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 执行下一步
    }
  }
})

Jump to the global post hook:

The document mentioned that because router.afterEach does not accept nextfunctions , it will not change the navigation itself, which means that it can only be used as a hook, but when I tried it myself, I found that we can use this form to achieve jumps:

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

s-z-h

Guess you like

Origin blog.csdn.net/qq_54753561/article/details/122352723
Recommended