权限需求是前端比较常见的,但是因为每个团队,确切的说是每个后台思想不同,所以做法各异。
现在我们团队中的后台,是返回一个标志数组,这个数据中记录了一些菜单的标志,以便于前端进行判断,那些菜单需要显示或者不显示。
比如后台返回一个权限的标志数据:
['menu1', 'menu2', ...]
前端的路由只能全部写死,然后递归判断,比如:
// 前端路由表
const routes = [
{
path: '/menu1',
meta: {
...
// 这里有个flag 用来对比后台返回的标志
flag: 'menu1'
}
},
......
];
然后在前端写一个方法进行递归遍历,确认哪些是需要,哪些是不需要的,方法如下:
* 匹配权限路由
* @param {*} target 是路由表
* @param {*} roles 是后台返回的标志数组
* @return {*}
*/
function matchMenu(target, roles) {
if (!roles || roles.length === 0) return;
let result = [];
target.forEach(menu => {
if (roles.indexOf(menu.meta.menuMatch) > -1) {
if (menu.children) {
menu.children = matchMenu(menu.children, roles)
}
result.push(menu)
}
})
return result
}
如上处理,最终可以得到相应的菜单路由。
但是,有个重要的问题忽略了。
我们操作的是一个数组,那就有深拷贝和浅拷贝之间的问题。
如果像上边这样做的话,每次改变了权限,会发现每次都要在刷新一遍页面,才能正确的显示菜单。
这一开始,我很奇怪。就不知道哪里出了错误,好长时间之后。终于明白是深浅拷贝的问题。
直接引入lodash
import _ from 'lodash';
Vue.prototype._ = _;
if (sessionStorage.getItem("leftMenu")) {
let str = window.sessionStorage.getItem("roles");
let roles = JSON.parse(str);
// 这里处理深浅拷贝
let obj = this._.cloneDeep(firstLevelRoutes);
let _leftMenu = matchMenu(obj, roles);
console.log('_leftMenu', _leftMenu);
initRoute(_leftMenu);
}
折腾完毕。