zoukankan      html  css  js  c++  java
  • VUE 动态路由

      因公司业务的发展,需要做一款新的产品,该产品分为:用户端和后台管理。我负责后台管理系统的开发。在看了UI的设计图后,又因为产品的周期较短,所以,我果断采用了vue-element-admin 来快速的搭建后台管理系统。这里我主要说下在这个过程中用到的动态路由,简单的总结下。

    vue-element-admin 本身的动态路由 (个人的理解)

    • 登录成功后获取token,根据 token 来获取用户信息和权限

      const { roles } = await store.dispatch('user/getInfo')
      // generate accessible routes map based on roles
      const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
      
    • 事先把不需要权限都能访问的路由 和 需要权限访问的路由都分配好后,在permission文件中导入

      import { asyncRoutes, constantRoutes } from '@/router'
      
    • 再调用 action 里的 generateRoutes 方法来根据用户的权限对路由进行不同的处理,并存储在state中

      generateRoutes({ commit }, roles) {
        return new Promise(resolve => {
          let accessedRoutes
          if (roles.includes('admin')) {
            accessedRoutes = asyncRoutes || []
          } else {
            accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
          }
          commit('SET_ROUTES', accessedRoutes)
          resolve(accessedRoutes)
        })
      }
      
      export function filterAsyncRoutes(routes, roles) {
        const res = []
      
        routes.forEach(route => {
          const tmp = { ...route }
          if (hasPermission(roles, tmp)) {
            if (tmp.children) {
              tmp.children = filterAsyncRoutes(tmp.children, roles)
            }
            res.push(tmp)
          }
        })
      
        return res
      }
      
      function hasPermission(roles, route) {
        if (route.meta && route.meta.roles) {
          return roles.some(role => {
            return route.meta.roles.includes(role)
          })
        } else {
          return true
        }
      }
      
    • 将生成的路由通过addRoutes动态添加进去

      router.addRoutes(accessRoutes)
      
    • 将state中的路由通过getters暴露出去,并生成侧边栏

      permission_routes: state => state.permission.routes,
      
      <el-scrollbar wrap-class="scrollbar-wrapper">
        <el-menu
          :default-active="activeMenu"
          :collapse="isCollapse"
          :background-color="variables.menuBg"
          :text-color="variables.menuText"
          :unique-opened="false"
          :active-text-color="variables.menuActiveText"
          :collapse-transition="false"
          mode="vertical"
        >
          <sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
        </el-menu>
      </el-scrollbar>
      

      我自己在此基础上改动的动态路由

        因为上述的动态是动态获取用户的权限来生成对应的路由的,登录成功后生成的路由不会在切换页面时发生改变。这和我们交互需求不符合,而且我们后端的登录接口,是一下将用户的token和用户的信息都返回了,并且没有用户的权限,也就是说我们的用户所有页面都是可以访问的。

      我的思路

      • 我将所有的路由都分配成了可访问的同步路由,没有异步路由

      • 并将所有的页面 (除登录、404页面),都在meta中添加了roles,并根据需求为每个页面添加对应的权限属性值。

      • permission 中定义了一个变量来表示路由状态,并定义对应的修改方法,最后将变量暴露出去,并将状态存储到了 sessionStorage 中

        routerstatus: sessionStorage.getItem('ifrouter') || false
        
      • 在渲染侧边栏的时候监听该值的变化,定义 setTimeout 的原因是当该值发生变化后,发现侧边栏不动态改变,而试了this.$forceUpdate()没有用,就采用这个方法

        watch: {
          routerstatus(newv, oldv) {
            if (newv) {
              this.ifRouter(this.transferarr)
            } else {
              this.ifRouter(this.outsidearr)
            }
            sessionStorage.setItem('ifrouter', newv)
            this.isshow = false
            const timer = setTimeout(() => {
              this.isshow = true
              clearTimeout(timer)
            }, 500)
          }
        },
        <!-- 这里的代码和我上述的思路有一定的出入,后续优化掉,更新掉 -->
        ifRouter(routerarr) {
          const temp_route_arr = this.$router.options.routes
          for (let i = 0; i < temp_route_arr.length; i++) {
            if (temp_route_arr[i].children && routerarr.includes(temp_route_arr[i].children[0].name)) {
              temp_route_arr[i].hidden = false
            }
            if (temp_route_arr[i].children && !routerarr.includes(temp_route_arr[i].children[0].name)) {
              temp_route_arr[i].hidden = true
            }
          }
        }
        <!-- 这里是稍作优化后的代码,随后有优化,会及时的更新 -->
        ifRouter(control) {
          const temp_route_arr = this.$router.options.routes
          for (let i = 0; i < temp_route_arr.length; i++) {
            if (temp_route_arr[i].meta && temp_route_arr[i].meta.roles.includes(control)) {
              temp_route_arr[i].hidden = false
            } else {
              temp_route_arr[i].hidden = true
            }
          }
        }
        
      • 这样通过动态的改变某个页面路由的 hidden 属性,来显示或隐藏页面,可以实现在切换页面时来动态改变侧边栏

      有想法的欢迎留言,一起学习成长

  • 相关阅读:
    Java&Go三种HTTP服务端端性能测试
    利用闭包实现自定义等待方法
    LevelDB在测试中应用应用
    利用Java反射处理private变量
    FunTester2021年总结
    推倒重来的觉悟
    SpringMVC项目依赖和静态资源导出
    DES算法详解
    5G AKA协议详解
    RSA算法加解密证明过程
  • 原文地址:https://www.cnblogs.com/aloneer/p/15063758.html
Copyright © 2011-2022 走看看