vue项目权限菜单实现
Vue 项目权限菜单实现方法
基于路由的权限控制
通过路由配置动态生成菜单,结合用户角色过滤可访问的路由。路由配置中添加 meta 字段标记权限:
const routes = [
{
path: '/admin',
component: AdminPanel,
meta: { requiresAuth: true, roles: ['admin'] }
}
];
在路由全局守卫中校验权限:
router.beforeEach((to, from, next) => {
const userRoles = store.getters.roles;
if (to.matched.some(record => record.meta.roles)) {
if (!userRoles.some(role => to.meta.roles.includes(role))) {
next({ path: '/403' });
}
}
next();
});
后端返回菜单结构
后端接口返回用户权限菜单的树形结构,前端动态渲染。接口数据示例:
{
"menus": [
{
"name": "Dashboard",
"path": "/dashboard",
"children": []
}
]
}
前端通过递归组件渲染菜单:
<template>
<el-menu>
<menu-item v-for="item in menus" :key="item.path" :menu="item" />
</el-menu>
</template>
<script>
export default {
components: {
MenuItem: {
props: ['menu'],
template: `
<el-submenu v-if="menu.children" :index="menu.path">
<template #title>{{ menu.name }}</template>
<menu-item v-for="child in menu.children" :key="child.path" :menu="child" />
</el-submenu>
<el-menu-item v-else :index="menu.path">{{ menu.name }}</el-menu-item>
`
}
}
}
</script>
权限指令实现
自定义指令控制按钮级权限:
Vue.directive('permission', {
inserted(el, binding, vnode) {
const { value } = binding;
const permissions = store.getters.permissions;
if (!permissions.includes(value)) {
el.parentNode.removeChild(el);
}
}
});
使用方式:
<button v-permission="'user:delete'">删除用户</button>
动态路由加载
根据权限异步加载路由配置:
// 前端维护全部路由
const asyncRoutes = [
{ path: '/settings', component: () => import('./Settings.vue'), meta: { role: 'admin' } }
];
// 过滤路由
function filterRoutes(routes, roles) {
return routes.filter(route => {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role));
}
return true;
});
}
// 动态添加路由
const allowedRoutes = filterRoutes(asyncRoutes, userRoles);
router.addRoutes(allowedRoutes);
状态管理集成
Vuex 存储权限信息:
const store = new Vuex.Store({
state: {
menus: [],
permissions: []
},
mutations: {
SET_PERMISSIONS(state, payload) {
state.permissions = payload.permissions;
state.menus = payload.menus;
}
},
actions: {
async fetchPermissions({ commit }) {
const res = await api.getPermissions();
commit('SET_PERMISSIONS', res.data);
}
}
});
按钮级权限组件
封装权限判断组件:
<template>
<slot v-if="checkPermission" />
</template>
<script>
export default {
props: {
permission: String
},
computed: {
checkPermission() {
return this.$store.getters.permissions.includes(this.permission);
}
}
}
</script>
使用方式:
<permission-check permission="user:edit">
<button>编辑</button>
</permission-check>






