• vue——路由守卫beforeEach,next(), next('/'), next({...to, repalce: true})说明及实例问题 前端


    参考: 手摸手,带你用vue撸后台 系列二(登录权限篇) - SegmentFault 思否

           VUE 路由守卫 next() / next({ ...to, replace: true }) / next(‘/‘) 说明_cimo的博客-CSDN博客_replace: true

          导航守卫 | Vue Router (vuejs.org)

          Error: Redirected when going from “/login?redirect=%2Fdashboard“ to “/dashboard“ via a navigation_Tom__cy的博客-CSDN博客

    一. 说明

    导航守卫官方文档:

    在路由守卫中,只有next()是放行,其他的诸如:next('/login') 、 next(to) 或者 next({ ...to, replace: true })都不是放行,而是:中断当前导航,执行新的导航

    例1:

    beforeEach((to, from, next) => {
      next('/login')
    }

    实际执行流程:

    beforeEach((to, from, next) => {
      beforeEach(('/login', from, next) => {
           beforeEach(('/login', from, next) => {
                beforeEach(('/login', from, next) => {
                    beforeEac...  // 一直循环下去...... , 因为没有使用 next() 放行
             }
          }
      }
    }

    例2:

    beforeEach((to, from, next) => {
       if(to.path === '/home') {
           next('/login')
       } else {
        // 如果要去的地方不是 /home , 就放行
           next()
       }
    }

    访问 '/home' ,执行第一次 beforeEach,但是这个路由守卫中判断了如果要去的地方是'/home',就执行next('/login'),流程如下:

    beforeEach((to, from, next) => {
       beforeEach(('/login', from, next) => {
         next()  // 现在要去的地方不是 /home , 因此放行
       }
    }

    重点,next('/login')不是说直接去/login路由,而是中断(不是CPU的那个中断!VUE中的中断就是此时不会执行router.afterEach(() => {})这一次路由守卫的操作,

       又进入一次路由守卫,就像嵌套一样,一层路由守卫,然后又是一层路由守卫,此时路由守卫进入到第二层时,to.path已经不是/home了,这个时候才执行next()放行操作。

    二. 实例

    我的情况:有基础路由,其余路由,由后端根据用户权限返回,前端使用addRoutes()动态添加

    问题1:addRoutes()之后第一次访问被添加的路由会白屏

    原因:此时addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。

    解决方案:使用next({ ...to, replace: true })来确保addRoutes()时动态添加的路由已经被完全加载上去(使用next()的话,传到钩子函数里的to参数 是添加路由之前的值(这个to的参数是值传递),所以不行)

         replace: true 只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。

         next({ ...to})执行很简单,它会判断:

         如果参数to不能找到对应的路由的话,就再执行一次beforeEach((to, from, next)直到其中的next({ ...to})能找到对应的路由为止。     

         也就是说此时addRoutes()已经完成啦,找到对应的路由之后,接下来将执行前往对应路由的beforeEach((to, from, next) ,因此需要用代码来判断这一次是否就是前往对应路由的beforeEach((to, from, next),如果是,就执行next()放行。

         如果守卫中没有正确的放行出口的话,会一直next({ ...to})进入死循环 !!!

         因此你还需要确保在当addRoutes()已经完成时,所执行到的这一次beforeEach((to, from, next)中有一个正确的next()方向出口

    main.js/router.js:

    router.beforeEach((to, from, next) => {
      if (store.getters.token) { // 判断是否有token
        if (to.path === '/login') { // 登录过就不能访问登录界面,需要中断这一次路由守卫,执行下一次路由守卫,并且下一次守卫的to是主页
          next({ path: '/' });
        } else {
          if (store.getters.addRoutes.length === 0) { // 判断是否已生成过动态路由
            store.dispatch('generateRoute').then(res => { // 异步操作,获取用户的权限,与已设置好的路由进行对比,筛选出用户可访问的动态路由,存放在store的addRoutes变量中
              router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
              next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
            }).catch(err => {
              console.log(err);
            });
          } else {
            next() // 已生成过动态路由,直接进入
          }
        }
      } else { // 未登录
        if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
          next();
        } else {
          next('/login'); // 否则全部重定向到登录页
        }
      }
    });

     问题2:登录后,跳转首页控制台会报错

    Error: Redirected when going from "/login" to "/home" via a navigation guard.

    原因:

    next({ ...to, replace: true })会被认为是一个失败的navigation(虽然能导航成功,但不再是原来的to),所以login里的repalce()返回一个rejected Promise。

    解决方案:

    在replace()后面接一个.catch(()=>{})

  • 相关阅读:
    CentOS7下Elastic Stack 5.0日志分析系统搭建
    ElasticSearch 简单入门
    简单使用packetbeat
    centos7没有安装ifconfig命令的解决方法
    CentOS系统下docker的安装与卸载
    centos7 cannot find a valid baseurl for repo base
    HP P2xxx/MSA SMI-S Provider
    Zookeeper 的学习与运用
    kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
    利用开源架构ELK构建分布式日志系统
  • 原文地址:https://www.cnblogs.com/linjiangxian/p/15827323.html
Copyright © 2020-2023  润新知