概述
公司后台管理系统,需要从后端获取路由表,并正确渲染。结合看到的帖子 基于vue-router的动态权限实现方案,昨天将这个需求实现了。
实现这个问题,有两个关键点。
- 登陆系统和刷新页面时,使用
router.addRoutes
添加需要补充的路由表 - 在
router.beforeEach
中,手动将路由表加到router.options.routes
中
公司后台管理系统开发使用的模板是后台管理系统模板vue-admin-template。需要新增或改动的文件主要有4个:
- 在store/modules文件夹下新增的menu.js:处理并存储从后端获取的路由
- 修改router/index.js:只保留登陆页面的路由,其他和业务板块相关路由都删掉
- 修改permission.js:实现刷新页面时动态添加路由表,并手动给
router.options.routes
赋值 - 修改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。这是系统的登录页面,密码验证通过后,做三件事。
- 将后端返回的路由表,存到localStorage中,
window.localStorage.setItem('permission', menu);//menu:string类型
- 将后端取到的路由表,存到vuex中,
this.$store.dispatch('addMenu',menuArr);//menuArr:数组类型
-
第一次登陆时,将新增的路由通过addRoutes加到router中
if(!this.hasPermission){ this.$router.addRoutes(this.menuitems); }
总结
menu.js中将拿到的路由表进行处理,转化为可以直接addRoutes
的路由表
permission是处理刷新时,路由的挂载和router.options.routes
的赋值
checkPwd存储拿到的路由表。
我在做的时候,踩过的坑有:
- 第一次登录时,不渲染。原因是第一次登陆时,permission为空,没有调用addRoutes,路由没挂载
- 菜单栏,相同路由有多个。原因是在给
router.options.routes
赋值时,采用了push方法。
以上就是我要分享的内容,不足的地方还请大家多多指正。