前言
当管理员角色对菜单数据进行增删改操作时,要求左侧菜单栏动态更新。
思路:增删改时重新获取菜单并重新添加菜单路由以及将菜单数据存入vuex,利用vuex的数据变更具有实时性的特点进行实现。
一、以新增菜单为例
这里获取到后台返回的操作结果后进行重新获取菜单并添加路由的操作
submitAdd() {
this.$refs.formAdd.validate((valid) => {
if (valid) {
this.submitLoading = true;
insertSysMenu(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.code) {
this.$Message.success(res.msg);
//重新获取菜单并添加路由
util.findMenuData();
this.menuModalVisible = false;
}
});
}
});
}
二、重新获取菜单并重新添加菜单路由以及将菜单数据存入vuex
util.findMenuData = function(){
findAllMenuTree().then((res)=>{
//console.log("菜单树===>"+JSON.stringify(res));
if(res.code == 200){
//将获取的菜单数据放入localStorage中备用(处理刷新页面路由丢失的问题)
store.commit("users/setMenu", {
menuData: res.result
});
let menuRoutes = [];
menuRoutes = util.initMenu(menuRoutes,res.result);
//将获取到的菜单数据重新添加到路由并存入vuex
store.commit('users/updateRouter',menuRoutes);
}
})
.catch(err =>{
console.log("获取菜单数据报错=="+err);
})
}
// 生成路由节点
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;
}
//注: store.js
state: {
routers: []
},
mutations: {
setMenu(state,{menuData}){
//刷新页面localStorage缓存数据不丢失
localStorage.setItem("menuData",JSON.stringify(menuData));
},
// 动态添加主界面路由
updateRouter(state,routes) {
//...代表存入数组
state.routers = routes;
router.addRoutes(routes);
}
}
三、菜单渲染
initMenuData(){
//利用的vuex的数据变更具有实时性的特点
this.menuList = this.$store.state.users.routers;
}
<Menu ref="side_menu" :active-name="childActiveMenu" theme="dark" width="auto" :open-names="[parentActiveMenu]" accordion @on-select="m=>{select(m)}">
<!--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>