需求:用户登录后获取相应的菜单权限,这里已知后台获取的菜单树
这里介绍两种方式:
1、根据从后台获取的路由路径动态注册路由(import到项目),在前端配置菜单权限时需提交路由的路径给后台;
2、前端代码中将所有的路由路径注册好(全部import到项目),由于路由全部注册好了,根据后台返回的菜单显示即可;但这样在地址栏输入路由还是可以访问到,所以前端配置菜单权限时需要给后台提交相应的接口权限,用户登录后没有这个菜单的接口权限则输入地址栏也无权访问,保证正确性。
两种方式的区别:
第一种是通过后台获取菜单之后去注册路由,那么地址栏输入路由就会报404
第二种是全部注册好路由,地址栏输入不会报404,这时候需要控制接口权限
方式一:动态注册路由
loadingRoutes.js
/*
动态注册路由
页面全在views文件夹下
如:
import page1 from './views/page1.vue'
import page2 from './views/page/page2.vue'
*/
export default (name) => () => import(`@/views/${name}.vue`)
menuUtils.js
// 引入注册路由方法
import loadingRoutes from './loadingRoutes'
export default (routers, data) => {
//转换服务端菜单数据,拿到自己想要的字段,比如这里的路由路径component (或者其他的key)
generaMenu(routers, data)
}
function generaMenu(routers, data) {
if (data) {
data.forEach((item) => {
//这里在和后台规定如果是按钮权限component字段为'/' ,权限按钮为弹出框,没有路由
if (item.path == "/") {
return false;
}
let menu = Object.assign({}, item);
if (menu.component == "home") {
menu.component = require("@/views/Home.vue");
menu = Object.assign({redirect: item.children?item.children[0].path:"/main"}, menu);
} else {
// 注册加载相应路由
menu.component = loadingRoutes (menu.component)
}
//有子菜单
if (item.leaf == "true") {
menu.children = [];
generaMenu(menu.children, item.children)
}
// 将菜单push进路由
routers.push(menu)
})
}
}
home.vue
created() {
//这里没有直接使用this.$router.options.routes,是因为addRoute的路由规则,在这里this.$router.options.routes获取不到
//另外在开发的时候,可能由于是热部署,也会不断重复的给nodes添加元素,造成导航条有重复的,简单解决,可以设置一个开关
let isLoadNodes = sessionStorage.getItem('isLoadNodes');
if (!isLoadNodes) {
let menuInfo = sessionStorage.getItem('menuInfo');
if (menuInfo) {
let data = JSON.parse(window.sessionStorage.getItem('menuInfo'));
this.nodes.push(...data);
sessionStorage.setItem('isLoadNodes', 'true')
} else {
//this.$api.getMenus({roleId: getCookie('property_roleId')}).then((res) => {
this.$api.getMenus({roleId: sessionStorage.getItem('property_roleId')}).then((res) => {
if (this.$util.checkCode(this, res)) {
this.nodes.push(...res.data);
sessionStorage.setItem('isLoadNodes', 'true')
}
});
}
}
},
routes.js
const router = new Router({
mode: 'history',
routes
});
// 引入MenuUtils
import MenuUtils from '@/scripts/common/MenuUtils'
let data = JSON.parse(window.sessionStorage.getItem('menuInfo'))
if (data) {
//这里是防止用户手动刷新页面,整个app要重新加载,动态新增的路由,会消失,所以需要重新add一次
// 或者通过vuex保存菜单,重新赋值 这里不做说明
let routes = [];
MenuUtils(routes, data);
router.addRoutes(routes);
window.sessionStorage.removeItem('isLoadNodes');
}
方式二:注册好全部路由,后台控制接口访问权限
方式二其实更简单,由于路由全部注册好了,通过后台返回的菜单树进行显示即可,这里不做详细说明。
如果采用vuex保存菜单,注意刷新的时候重新获取菜单。
本篇文章偏向于说明动态获取菜单的思想,有什么不足的地方或疑问欢迎指出来,谢谢大家~
网友评论