对于菜单权限我们需要解决以下问题:
1、不同的账号登录,有不同的菜单
2、通过输入url地址来显示页面,所以应该根据权限动态注册路由
3、对于菜单数据,在不同页面之间的数据通信
现在项目中的菜单,我们是在 CommenAside 中写死的,现在我们需要根据登录后返回的权限动态展示,所以我们找到登录后的代码,修改 Login.vue,在 submit 方法登录成功后,将菜单数据存入 store 中
submit(){
//校验通过
this.$refs.form.validate((valid)=>{
if(valid){
getMenu(this.form).then(({data})=>{
// console.log('TTT',data);
if(data.code === 20000){
// token信息存入cookie用于不同页面间的通讯
Cookie.set('token',data.data.token);
// 获取菜单数据,存入store
this.$store.commit('setMenu',data.data.menu);
// 跳转首页
this.$router.push('home')
} else {
this.$message.error('账号信息错误');
}
})
}
})
}
修改 tab.js
import {findIndex} from "core-js/internals/array-iteration";
export default {
state:{
......
menu:[]
},
mutations:{
......
// 设置菜单
setMenu(state,val){
state.menu = val
}
}
}
然后修改 CommonAside 中的代码,我们定义一个计算属性 menuData,通过 store 中存入的 menu 获取,所以 data 中的 menuData 可以删掉了
<script>
export default {
data() {
return {};
},
......
computed:{
......
menuData(){
return this.$store.state.tab.menu;
}
}
}
</script>
登录成功后可以看到左侧菜单是展示的
但是现在存在一个问题,刷新后菜单就消失了
因为 store 中的 state 数据是存在浏览器的内存中的,所以刷新后就不存在了,所以如果需要持久化,就需要缓存
因为 Cookie 的数据必须是字符串,所以需要序列化字符串,所以修改 tab.js 中 setMenu 方法
setMenu(state,val){
state.menu = val;
Cookie.set('menu',JSON.stringify(val))
}
修改 CommonAside.vue 中获取菜单的方法
menuData(){
return JSON.parse(Cookie.get('menu')) || this.$store.state.tab.menu;
}
这样登录账号后,再刷新就不会有问题了
账号:admin
密码:admin
现在来解决第二个问题,如果我们登录另一个账号
账号:xiaoxiao
密码:xiaoxiao
可以看到左侧只有两个菜单了。但是有个问题是,如果我们在浏览器输入 /user 的链接,还是可以打开用户列表的页面
原因就是在 router/index.js 中我们是写死的这些路径
我们需要动态注册路由,在 tabs.js 中增加动态添加相应方法:
// 动态注册路由
addMenu(state,router){
}
在 Login.vue 中,当存入菜单后,调用 addMenu
// 获取菜单数据,存入store
this.$store.commit('setMenu',data.data.menu);
this.$store.commit('addMenu',this.$router);
tab.js 中添加动态注册路由的方法
// 动态注册路由
// 动态注册路由
addMenu(state,router) {
// 判断当前缓存中是否有数据
if (!Cookie.get('menu')) return
const menu = JSON.parse(Cookie.get('menu'))
state.menu = menu
// 动态组装路由数据
const menuArray = []
menu.forEach(item =>{
// 有子菜单
if(item.children){
item.children = item.children.map(item=>{
item.component = ()=> import(`../views/${item.url}`)
return item
})
menuArray.push(...item.children)
}else {
// 没有子菜单
item.component = ()=> import(`../views/${item.url}`)
menuArray.push(item)
}
})
// console.log('menuArray',menuArray);
//路由的动态添加
menuArray.forEach(item=>{
router.addRoute('Main',item);
})
}
我们看下打印结果:
由于上边动态添加路由时:router.addRoute('Main');
使用的是 name 属性,所以修改 index.js,给主路由增加 name 属性
最后,找到登出位置 CommonHeader.vue,在登出的时候清空 Cookie中的menu数据
handleCommand(command){
if(command === 'cancel'){
.....
// 清除Cookie中的menu数据
Cookie.remove('menu');
......
}
}
最后在 index.js 中注释掉写死的路由数据
下面进行测试,首先登录 admin/admin,可以看到显示了全部的菜单
退出,然后登录 xiaoxiao/xiaoxiao,可以看到只有首页和商品管理两个菜单
再次输入 /user 可以看到访问不到了
现在有一个问题就是刷新以后页面是空白的,原因就是登录以后调用了 addMenu,刷新后整个 vue 实例已经初始化了,就不会走这个方法了,我们需要在 main.js 中修改初始化 vue 实例,在 created 时再次走 addMenu 方法
new Vue({
router,
store,
render: h => h(App),
created() {
store.commit('addMenu',router)
}
}).$mount('#app')
资源下载