大大小小做过不少的后台系统,从登录权限到路由权限等等。在项目中也有遇到遇到很多问题,在此就菜单权限以及路由权限进行总结。
方式1(路由钩子函数里判断)
前端定义路由,配置好路由表,代码示例
{
path: '/path',
component: () => import('./component'),
name: 'componentName',
meta: {
menuName:'菜单名称'
auth: 'authCode'
}
}
在登录的时候后台会返回一串有权限的代码codeList,将这个codeList和本地路由进行相对比,筛选出对应的权限路由,并保存到本地。菜单结构和路由表结构保持一致,路由表既是菜单结构,从而渲染。 在路由钩子函数判断用户是否具有路由meta所标注的authCode,没有权限则跳到事先定义好的界面
缺点
- 每次跳转都要做权限判断
- 菜单信息写死在前端,要改个显示文字或权限信息,需要重新编译,并且发版本
- 菜单跟路由耦合在一起,定义路由的时候还有添加菜单显示标题,图标之类的信息,有时候路由不一定要作为菜单展示,需要另外加字段不方便
方式2(使用addRoutes挂载路由)
路由权限
前端定义路由,配置好路由表,代码示例
{
path: '/path',
component: () => import('./component'),
name: 'componentName',
meta: {
menuName:'菜单名称'
auth: 'authCode'
}
}
在登录的时候后台会返回一串有权限的代码codeList,将这个codeList和本地路由进行相对比,筛选出对应的权限路由,并保存到本地。由此生成对应的路由表。在路由钩子函数中使用add.Routes实现路由动态添加,并实现相对应的判断。注意的是{ path: '*', redirect: '/404' }必须放在最后一位,否则会覆盖。代码示例
router.beforeEach((to, from, next) => {
if (['/login'].includes(to.path)) {
store.commit('publicModule/SET_ROUTEHAVE', false)
removeMenu('menuList');
next();
} else if (token) {
if (!store.state.publicModule.routerHave) {
//生成后匹配权限的路由表
var routers = constantRouterMap();
if (!routers) {
store.commit('publicModule/SET_ROUTEHAVE', true)
return next('/no-premission')
}
store.commit('publicModule/SET_MENUS', routers)
store.commit('publicModule/SET_ROUTEHAVE', true)
router.addRoutes(routers)
return next({ ...to, replace: true });
} else {
next()
}
} else {
next({ path: '/login' });
}
});
菜单权限
这种方式的菜单是根据我们匹配出来的路由表生成,并渲染的(当然,结构需要保持一致)
缺点
- 菜单信息写死在前端,要改个显示文字或权限信息,需要重新编译,并且发版本
- 菜单跟路由耦合在一起,定义路由的时候还有添加菜单显示标题,图标之类的信息,有时候路由不一定要作为菜单展示,需要另外加字段不方便
方式三
菜单权限
登录的时候后端就返回菜单,进到主界面的时候就进行了渲染。
路由权限 前端配置一个key-value格式的路由表
const componentName = () => import("/path-component-name");
export default {
componentName
};
后端约定返回:
{
name: "componentName",
path: "/componentName",
component: "componentName"
},
后端返回了路由的时候,通过addRoutes动态挂载之间,将数据处理一下(将component字段替换成我们需要的组件,myCOnfig[component]如此)
优点
感觉就前端来说相对省事一点,只要渲染就行了,不需要进行匹配。菜单顺序、标题、图标也都可配置,如果需要进行修改,也不需要前端修改并发包。
按钮权限
后台系统中所对应的按钮,如增删改等权限,我们也是在登录中返回的auth。前端中写了一个指令,如下
import Vue from 'vue'
let action = function(el, binding, vnode) {
const { value } = binding
const premissionList = JSON.parse(localStorage.getItem('userAuths')) || [];
if (value) {
const permissions = value.split(',');
const hasPermission = permissions.some(cur => premissionList.includes(cur))
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
const premission = Vue.directive('limit', {
inserted(el, binding, vnode) {
action(el, binding, vnode)
},
update(el, binding, vnode) {
action(el, binding, vnode)
},
})
export default premission
在页面中使用:
<el-button
type="primary"
@click="handleDelete"
v-limit="'CONSOLE_AGENT_DRUG_DELETE'"
><i class="el-icon-delete el-icon--left"></i>删除</el-button>