美文网首页前端
vue.js动态获取菜单

vue.js动态获取菜单

作者: 我追求的小世界 | 来源:发表于2018-10-10 11:51 被阅读0次

    需求:用户登录后获取相应的菜单权限,这里已知后台获取的菜单树

    这里介绍两种方式:

    1、根据从后台获取的路由路径动态注册路由(import到项目),在前端配置菜单权限时需提交路由的路径给后台;
    2、前端代码中将所有的路由路径注册好(全部import到项目),由于路由全部注册好了,根据后台返回的菜单显示即可;但这样在地址栏输入路由还是可以访问到,所以前端配置菜单权限时需要给后台提交相应的接口权限,用户登录后没有这个菜单的接口权限则输入地址栏也无权访问,保证正确性。

    两种方式的区别:

    第一种是通过后台获取菜单之后去注册路由,那么地址栏输入路由就会报404
    第二种是全部注册好路由,地址栏输入不会报404,这时候需要控制接口权限

    方式一:动态注册路由

    loadingRoutes.js

    /*
    动态注册路由
    页面全在views文件夹下
    如:
    import page1 from './views/page1.vue'
    import page2 from './views/page/page2.vue'
    */
    export default (name) => () => import(`@/views/${name}.vue`)
    
    

    menuUtils.js

    // 引入注册路由方法
    import loadingRoutes from './loadingRoutes' 
    
    export default (routers, data) => {
      //转换服务端菜单数据,拿到自己想要的字段,比如这里的路由路径component (或者其他的key)
      generaMenu(routers, data)
    }
    
    function generaMenu(routers, data) {
      if (data) {
        data.forEach((item) => {
          //这里在和后台规定如果是按钮权限component字段为'/' ,权限按钮为弹出框,没有路由
          if (item.path == "/") {
            return false;
          }
          let menu = Object.assign({}, item);
          if (menu.component == "home") {
            menu.component = require("@/views/Home.vue");
            menu = Object.assign({redirect: item.children?item.children[0].path:"/main"}, menu);
          } else {
           // 注册加载相应路由
            menu.component = loadingRoutes (menu.component)
          }
           //有子菜单
          if (item.leaf == "true") {
            menu.children = [];
            generaMenu(menu.children, item.children)
          }
          // 将菜单push进路由
          routers.push(menu)
        })
      }
    }
    
    

    home.vue

     created() {
          //这里没有直接使用this.$router.options.routes,是因为addRoute的路由规则,在这里this.$router.options.routes获取不到
          //另外在开发的时候,可能由于是热部署,也会不断重复的给nodes添加元素,造成导航条有重复的,简单解决,可以设置一个开关
       let isLoadNodes = sessionStorage.getItem('isLoadNodes');
       if (!isLoadNodes) {
         let menuInfo = sessionStorage.getItem('menuInfo');
         if (menuInfo) {
           let data = JSON.parse(window.sessionStorage.getItem('menuInfo'));
           this.nodes.push(...data);
           sessionStorage.setItem('isLoadNodes', 'true')
         } else {
           //this.$api.getMenus({roleId: getCookie('property_roleId')}).then((res) => {
           this.$api.getMenus({roleId: sessionStorage.getItem('property_roleId')}).then((res) => {
             if (this.$util.checkCode(this, res)) {
               this.nodes.push(...res.data);
               sessionStorage.setItem('isLoadNodes', 'true')
             }
           });
         }
       }
     },
    

    routes.js

    const router = new Router({
      mode: 'history',
      routes
    });
    // 引入MenuUtils 
    import MenuUtils from '@/scripts/common/MenuUtils'
    let data = JSON.parse(window.sessionStorage.getItem('menuInfo'))
    if (data) {
      //这里是防止用户手动刷新页面,整个app要重新加载,动态新增的路由,会消失,所以需要重新add一次
      // 或者通过vuex保存菜单,重新赋值  这里不做说明
      let routes = [];
      MenuUtils(routes, data);
      router.addRoutes(routes);
      window.sessionStorage.removeItem('isLoadNodes');
    }
    
    方式二:注册好全部路由,后台控制接口访问权限

    方式二其实更简单,由于路由全部注册好了,通过后台返回的菜单树进行显示即可,这里不做详细说明。
    如果采用vuex保存菜单,注意刷新的时候重新获取菜单。

    本篇文章偏向于说明动态获取菜单的思想,有什么不足的地方或疑问欢迎指出来,谢谢大家~

    相关文章

      网友评论

        本文标题:vue.js动态获取菜单

        本文链接:https://www.haomeiwen.com/subject/gjhpaftx.html