动态路由中涉及到页面操作权限时的addRoute路由更新无效问题

场景

  • 网站根据用户等级有操作权限的限制,不光是菜单列表不同,页面按钮的操作权限也不同,这肯定就需要和后台配合使用动态路由管理页面权限。而页面按钮的权限也需要在解析后台返回的json字段中带的权限字段来控制,所以也要放到router里,在页面访问时,通过$route获取当前页面的操作权限等级

问题

  • 现在遇到的问题是,首次登录或者刷新页面时,路由的解析都是正确的,没有任何问题,但是如果没有刷新页面,而是退出登录,切换了另一个权限级别的账户,登录之后的路由解析出来的是上一轮账户的权限等级。刷新之后又对了,现在如何不刷新,就能正确的切换用户权限级别?

解决

  • 先看路由解析,存页面权限,动态路由处理以前有分析过,跳转
    其实很简单,做好了路由解析,在路由对象的meta里存权限字段就行了,存其他地方好像通过$route拿不到,具体什么原因暂时没有深究。
    const currentRouter = {
      ...
      // meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
      meta: {
        title: item.title,
        icon: item.icon || undefined,
        hiddenHeaderContent: item.hiddenHeaderContent,
        target: item.target,
        permission: item.name,
        // 如果是个页面,保留它的权限字段
        jurisdiction: item.jurisdiction || undefined
      }
    }
    
  • 然后是当前页面访问自己的页面权限,activated用于对被包裹的组件监听其活跃状态,每次重新访问页面时触发,这里我们用包裹整个路由页面的,就能对所有页面监听activated
    activated () {
      // 访问当前页面权限字段,权限解析自行处理
      console.log(this.$route.meta.jurisdiction)
    }
    
  • vue2中可封装成mixin,vue3中可封装成derocator
  • 以上都是基本思路,这样走下来,就会遇到笔者开始提到的问题了。切换另一个权限级别的用户时,路由里的权限等级没有更新。
    • 分析:
      既然刷新没问题,只是在重登的时候出了问题,那问题就应该是出在重登时的路由解析。
      这段代码是哪儿出了问题呢?
      经过排查,每次重登处理的addRouters都是正确的,带的权限字段是对的,但是在addRoute之后的router却有问题,输出的路由表只有新增,没有清除第二次处理时没有的路由。那么就基本可以确认,是addRoute这里出了问题,它没有一个清空操作,所以导致多次处理之后的结果是路由累积。
      if (store.getters.addRouters.length === 0) { // 表示还没生成新路由
        store.dispatch('GenerateRoutes', { roles }).then(() => {
          // 重登后的addRouters是更新了的
          const addRouters = store.getters.addRouters
          for (let i = 0; i < addRouters.length; i++) {
            router.addRoute(addRouters[i])
          }
          console.log(router.getRoutes()) // 查看更新后的router的路由表
          const redirect = decodeURIComponent(from.query.redirect || to.path)
          if (to.path === redirect) {
            next({ ...to, replace: true, query: to.query })
          } else {
            next({ path: redirect, query: to.query })
          }
        })
      } else {
        next()
      }
      
    • 解决思路
      既然是没有清空,那可不可以重新声明一个Router,然后再addRoute呢?
      下面的代码,我们再addRoute之前,先重声明一个Router,并将它的matcher给到原router,这样router的路由匹配就是走的新的Router,但是,重点,一开始忽略了一个东西,导致出了点问题,卡了很久。重点是重新声明的Router不要忘记配一下静态路由,比如登录页,404页这些都是放在静态路由里的,不是通过后台返回的json解析的,如果忘了它们,就会少几个页面了。
      所以这里routes: constantRouterMap就是引入静态路由
      if (store.getters.addRouters.length === 0) { // 表示还没生成新路由
        store.dispatch('GenerateRoutes', { roles }).then(() => {
          // 重登后的addRouters是更新了的
          const addRouters = store.getters.addRouters
          router.matcher = new Router({
            mode: 'hash', //
            routes: constantRouterMap, // 引入的公共路由
            base: process.env.BASE_URL
          }).matcher // reset router
          for (let i = 0; i < addRouters.length; i++) {
            router.addRoute(addRouters[i])
          }
          const redirect = decodeURIComponent(from.query.redirect || to.path)
          if (to.path === redirect) {
            next({ ...to, replace: true, query: to.query })
          } else {
            next({ path: redirect, query: to.query })
          }
        })
      } else {
        next()
      }
      
    至此完成。
posted @ 2022-09-30 10:59  Mizuki-Vone  阅读(1404)  评论(0编辑  收藏  举报