8

概述

    公司后台管理系统,需要从后端获取路由表,并正确渲染。结合看到的帖子 基于vue-router的动态权限实现方案,昨天将这个需求实现了。
    实现这个问题,有两个关键点。

  1. 登陆系统和刷新页面时,使用router.addRoutes添加需要补充的路由表
  2. router.beforeEach中,手动将路由表加到router.options.routes

    公司后台管理系统开发使用的模板是后台管理系统模板vue-admin-template。需要新增或改动的文件主要有4个:

  1. 在store/modules文件夹下新增的menu.js:处理并存储从后端获取的路由
  2. 修改router/index.js:只保留登陆页面的路由,其他和业务板块相关路由都删掉
  3. 修改permission.js:实现刷新页面时动态添加路由表,并手动给router.options.routes赋值
  4. 修改checkPwd.vue:登陆成功时,将后端获取的路由表存到localstorage

    下面结合代码做具体说明:


第一步

从后端获取的路由表,是不能直接通过router.addRoutes添加到路由表里,需要先修改component属性的值。我是统一在menu.js中修改。menu.js中有三大部分内容。 routerMap(component属性值和业务模块的映射),menu对象,generateRoutesFromMenu和transferChildren(处理路由表)

routerMap是这样的:

const routerMap = {
    'Layout':() => import('@/views/layout/Layout'),
    'reportProIntro': () => import('@/views/reportSystem/reportProIntro/index'),
    'reportProDetail': () => import('@/views/reportSystem/reportProDetail/index'),
    'collectionDaily': () => import('@/views/reportSystem/collectionDaily/index'),
    'performanceRanking': () => import('@/views/reportSystem/performanceRanking/index')
    }

menu对象是这样的:

const menu = {
    state:{
        items:[]
    },
    mutations:{
        ADD_MENU: (state,menuItems) => {
            if(menuItems.length == 0){
                state.items = [];
            }else{
                state.items = menuItems;
            }
        }        
    },
    actions:{
        addMenu:({commit},menuItems) => {
            let menu = generateRoutesFromMenu(menuItems)
            menu.push(asyncRouterMap[0]);
            commit('ADD_MENU',menu);            
        }
    }
}
export default menu

generateRoutesFromMenu和transferChildren是这样的:

function generateRoutesFromMenu(menu = []){    
    menu[0].component = routerMap.Layout;
    menu[0].redirect = 'reportProIntro';
    menu[0].name = 'Example';
    menu[0].meta = { title: '报表中心', icon: 'example' };
    menu[0].children = transferChildren(menu[0].children);      
    return menu
}

function transferChildren(childrenArr){    
    //格式化name,component,meta属性  
    console.log(childrenArr)  
    childrenArr.map((cur,index)=>{
        cur.name = cur.path;
        cur.component = routerMap[cur.path];
        cur.meta = {'title':cur.title}
        if(cur.children.length > 0){
            transferChildren(cur.children)
        }
    })
    return childrenArr
}

因为后台返回的路由表格式不一样,大家要根据实际情况进行改动,改成可用的路由表。

menu.js中把路由表的处理和存储都做好了。在需要存储路由表的地方,使用dispatch,调用addMenu方法即可。

第二步

写好了menu.js后,再来修改permission.js文件。permission.js有两处需要改。

  • 刷新页面时,如果localStorage中有permission(checkPwd登录成功时,获取的路由表),则将路由表存到到vuex中,再取出来,通过router.addRoutes挂载到路由上
let permission = JSON.parse(window.localStorage.getItem('permission'));
/* 刷新页面时候加载路由 */
if(permission){
    store.dispatch('addMenu',permission)
    router.addRoutes(store.getters.menuitems) 
}else{
    router.push({
        name: "checkPwd"
      })
}
  • router.beforeEach中,手动将可用路由表menuitems加到router.options.routes
store.getters.menuitems.forEach((item,index) => {
    router.options.routes[index+1] = item;
}) 

router.beforeEach中的这段代码,每次路由跳转时,都会调用。本项目中,路由表是通过router.options.routes渲染到菜单栏,而router.addRoutes并不会改变router.options.routes的值,所以,如果不手动加上,那么菜单将不能正常渲染出来。

第三步

改好了permission.js文件,再来修改checkPwd.vue。这是系统的登录页面,密码验证通过后,做三件事。

  1. 将后端返回的路由表,存到localStorage中,window.localStorage.setItem('permission', menu);//menu:string类型
  2. 将后端取到的路由表,存到vuex中,this.$store.dispatch('addMenu',menuArr);//menuArr:数组类型
  3. 第一次登陆时,将新增的路由通过addRoutes加到router中

    if(!this.hasPermission){
         this.$router.addRoutes(this.menuitems);      
    }

总结

menu.js中将拿到的路由表进行处理,转化为可以直接addRoutes的路由表
permission是处理刷新时,路由的挂载和router.options.routes的赋值
checkPwd存储拿到的路由表。

我在做的时候,踩过的坑有:

  1. 第一次登录时,不渲染。原因是第一次登陆时,permission为空,没有调用addRoutes,路由没挂载
  2. 菜单栏,相同路由有多个。原因是在给router.options.routes赋值时,采用了push方法。

以上就是我要分享的内容,不足的地方还请大家多多指正。


joychenke
47 声望3 粉丝

业精于勤荒于嬉。加油ヾ(◍°∇°◍)ノ゙