Vue
前言
后台管理系统中,单一的静态路由配置满足不了多样化的菜单权限管理。
一、动态路由实现
后端返回当前登录角色拥有的菜单树数据。前端获取到数据后生成菜单路由节点并进行渲染菜单;
以下代码逻辑:调取后台接口获取到返回的菜单树。将获取到的菜单树通过工具类(util)的initMenu()方法生成路由节点。并将生成好的路由节点提交到路由(router.addRoutes())
findAllMenuTree().then((res)=>{
//console.log("菜单树===>"+JSON.stringify(res));
if(res.code == 200){
context.commit("setMenu", {
menuData: res.result
});
let menuRoutes = [];
menuRoutes = util.initMenu(menuRoutes,res.result);
//console.log("menuRoutes===>"+JSON.stringify(menuRoutes));
//提交路由写在store.js中
context.commit('updateRouter',menuRoutes);
}
})
.catch(err =>{
console.log("获取菜单数据报错=="+err);
})
工具类(util)
import lazyLoading from './lazyLoading.js';
let util = {};
// 生成路由节点
util.initMenu = function(menuRoutes,menuData){
for(var item of menuData){
//将item复制到空对象中,再复制给menu,等于重新new了一个新的含有item属性并且有属性值的对象
let menu = Object.assign({}, item);
if(null != menu.component){
//console.log("menu.component=="+menu.component);
//menu.component = import(`@/views/${menu.component}.vue`);
//不采用异步component组件值无法进行封装
menu.component = lazyLoading(menu.component);//异步
}else{
//如果父级菜单没有component组件,则默认放置{render: (e) => e("router-view")},否则将无法进行子菜单跳转
menu.component = {render: (e) => e("router-view")};
}
if(item.children && item.children.length >0){
menu.children = [];
this.initMenu(menu.children,item.children);
}
//浏览器信息:浏览器标题,第三方网页链接地址
let meta = {};
meta.title = menu.title ? menu.title : null;
meta.url = menu.url ? menu.url : null;
menu.mate = meta;
menuRoutes.push(menu);
}
return menuRoutes;
}
export default util;
lazyLoading.js
export default (url) => {
return () => import(`@/views/${url}.vue`)
}
store.js 提交路由节点代码
mutations: {
// 动态添加主界面路由
updateRouter(state,routes) {
//...代表存入数组
state.routers.push(...routes);
router.addRoutes(routes);
}
}
页面渲染
<template>
<div class="layout">
<Row type="flex" style="position:absolute;left:0;top:0;width:100%;height: 100%;">
<Col span="4" class="layout-menu-left">
<!--Menu 导航栏 parentActiveMenu+'' 例: parentActiveMenu = 1 => '1' -->
<Menu ref="side_menu" :active-name="childActiveMenu" theme="dark" width="auto" :open-names="[parentActiveMenu]" accordion>
<!--Submenu 一级菜单-->
<Submenu v-for="pmenu in menuList" :name="pmenu.id" :key="pmenu.id">
<template slot="title">
<Icon :type="pmenu.icon"></Icon>
{{pmenu.title}}
</template>
<MenuItem v-for="cmenu in pmenu.children" :name="cmenu.path" :key="cmenu.path">
<Icon :type="cmenu.icon"></Icon>
{{cmenu.title}}
</MenuItem>
</Submenu>
</Menu>
</Col>
</Row>
</div>
</template>
<script>
export default ({
data() {
return {
//菜单列表
menuList: []
};
},
methods: {
initMenuData(){
this.menuList = JSON.parse(localStorage.getItem("menuData"));
this.$router.push(this.menuList[0].children[0].path);
}
},
mounted(){
this.initMenuData();
}
})
</script>