告别权限判断烦恼:vue-vben-admin hooks体系之usePermission全解析
【免费下载链接】vue-vben-admin 项目地址: https://gitcode.com/gh_mirrors/vue/vue-vben-admin
在复杂的后台管理系统开发中,权限控制是一个绕不开的话题。你是否还在为如何优雅地实现按钮级别的权限控制而烦恼?是否还在为不同角色展示不同菜单而头疼?vue-vben-admin的usePermission钩子函数为这些问题提供了优雅的解决方案。本文将深入解析usePermission的实现原理和使用方法,帮助你轻松掌握权限判断逻辑。
权限体系概览
vue-vben-admin的权限系统基于RBAC(Role-Based Access Control,基于角色的访问控制)模型设计,通过钩子函数、状态管理和路由控制相结合的方式,实现了从路由到按钮的全链路权限控制。
权限控制主要涉及以下几个核心模块:
- 权限钩子:src/hooks/web/usePermission.ts - 提供权限判断的核心API
- 权限状态管理:src/store/modules/permission.ts - 管理权限相关状态
- 项目配置:src/settings/projectSetting.ts - 权限模式配置
- 角色枚举:src/enums/roleEnum.ts - 角色定义
权限模式
vue-vben-admin支持三种权限模式,可在项目配置中设置:
// src/settings/projectSetting.ts
const setting: ProjectConfig = {
// 权限模式
permissionMode: PermissionModeEnum.ROUTE_MAPPING,
// ...
}
三种权限模式分别是:
- ROUTE_MAPPING:路由映射模式,基于路由配置的角色信息进行权限控制
- ROLE:角色模式,直接通过角色判断权限
- BACK:后端模式,通过后端返回的权限码进行权限控制
默认使用ROUTE_MAPPING模式,这是一种灵活且易于维护的权限控制方式。
usePermission核心实现
usePermission钩子是权限判断的入口,提供了丰富的API来满足不同场景的权限判断需求。
核心API
usePermission主要提供了以下几个核心函数:
- hasPermission:判断是否有权限
- changeRole:切换角色
- refreshMenu:刷新菜单
- togglePermissionMode:切换权限模式
hasPermission实现原理
hasPermission是usePermission中最核心的函数,用于判断用户是否拥有某项权限。其实现逻辑如下:
// src/hooks/web/usePermission.ts
function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean {
// 默认可见
if (!value) {
return def;
}
const permMode = appStore.getProjectConfig.permissionMode;
if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) {
if (!isArray(value)) {
return userStore.getRoleList?.includes(value as RoleEnum);
}
return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;
}
if (PermissionModeEnum.BACK === permMode) {
const allCodeList = permissionStore.getPermCodeList as string[];
if (!isArray(value)) {
const splits = ['||', '&&'];
const splitName = splits.find((item) => value.includes(item));
if (splitName) {
const splitCodes = value.split(splitName);
return splitName === splits[0]
? intersection(splitCodes, allCodeList).length > 0
: intersection(splitCodes, allCodeList).length === splitCodes.length;
}
return allCodeList.includes(value);
}
return (intersection(value, allCodeList) as string[]).length > 0;
}
return true;
}
从代码中可以看出,hasPermission函数的逻辑主要分为以下几步:
- 如果没有传入权限判断条件,默认返回true(有权限)
- 根据当前权限模式,执行不同的权限判断逻辑
- 在ROUTE_MAPPING和ROLE模式下,通过角色列表判断权限
- 在BACK模式下,通过权限码列表判断权限
角色判断逻辑
在ROUTE_MAPPING和ROLE模式下,权限判断基于角色列表:
if (!isArray(value)) {
// 单个角色判断
return userStore.getRoleList?.includes(value as RoleEnum);
}
// 多个角色判断,只要有一个角色匹配即有权限
return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;
角色列表定义在src/enums/roleEnum.ts中:
// src/enums/roleEnum.ts
export enum RoleEnum {
// 超级管理员
SUPER = 'super',
// 测试角色
TEST = 'test',
}
实际项目中,你可以根据需要扩展更多角色。
权限码判断逻辑
在BACK模式下,权限判断基于后端返回的权限码:
const allCodeList = permissionStore.getPermCodeList as string[];
if (!isArray(value)) {
// 支持"||"和"&&"逻辑运算符
const splits = ['||', '&&'];
const splitName = splits.find((item) => value.includes(item));
if (splitName) {
const splitCodes = value.split(splitName);
return splitName === splits[0]
? // "||"逻辑,有一个权限码匹配即有权限
intersection(splitCodes, allCodeList).length > 0
: // "&&"逻辑,所有权限码都匹配才有权限
intersection(splitCodes, allCodeList).length === splitCodes.length;
}
return allCodeList.includes(value);
}
return (intersection(value, allCodeList) as string[]).length > 0;
这种方式支持复杂的权限判断逻辑,如"perm1||perm2"(拥有perm1或perm2权限)或"perm1&&perm2"(同时拥有perm1和perm2权限)。
权限判断实战
掌握了usePermission的实现原理后,让我们看看如何在实际项目中使用它进行权限判断。
基础使用方法
首先需要在组件中引入usePermission钩子:
import { usePermission } from '@/hooks/web/usePermission';
const { hasPermission } = usePermission();
然后就可以使用hasPermission函数进行权限判断了。
角色权限判断
判断用户是否为超级管理员:
const isSuper = hasPermission(RoleEnum.SUPER);
判断用户是否为超级管理员或测试角色:
const hasRole = hasPermission([RoleEnum.SUPER, RoleEnum.TEST]);
权限码判断
在BACK模式下,可以通过权限码判断权限:
// 判断是否有查看用户的权限
const canViewUser = hasPermission('user:view');
// 判断是否有编辑或删除用户的权限
const canEditOrDeleteUser = hasPermission('user:edit||user:delete');
// 判断是否同时有创建和审核用户的权限
const canCreateAndAuditUser = hasPermission('user:create&&user:audit');
组件级权限控制
在模板中,可以直接使用hasPermission进行条件渲染:
<template>
<button v-if="hasPermission('user:create')">创建用户</button>
<button v-if="hasPermission([RoleEnum.SUPER, RoleEnum.TEST])">测试按钮</button>
</template>
<script setup lang="ts">
import { usePermission } from '@/hooks/web/usePermission';
import { RoleEnum } from '@/enums/roleEnum';
const { hasPermission } = usePermission();
</script>
路由权限控制
在路由配置中,可以通过meta.roles指定访问该路由所需的角色:
// 示例路由配置
const routes: AppRouteRecordRaw[] = [
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index.vue'),
meta: {
roles: [RoleEnum.SUPER], // 只有超级管理员可以访问
title: '仪表盘',
},
},
];
路由权限控制的实现逻辑在src/store/modules/permission.ts中,通过buildRoutesAction函数构建有权限访问的路由列表。
高级功能
切换角色
usePermission提供了changeRole函数,可以动态切换用户角色:
const { changeRole } = usePermission();
// 切换为测试角色
changeRole(RoleEnum.TEST);
// 切换为多个角色
changeRole([RoleEnum.SUPER, RoleEnum.TEST]);
切换角色后,系统会自动刷新路由和菜单,只显示当前角色有权限访问的内容。
刷新菜单
当权限发生变化时,可以使用refreshMenu函数刷新菜单:
const { refreshMenu } = usePermission();
// 刷新菜单
refreshMenu();
这在权限动态变化的场景下非常有用,如管理员修改了用户的权限后,用户无需重新登录即可看到权限变更后的菜单。
切换权限模式
usePermission还提供了切换权限模式的功能:
const { togglePermissionMode } = usePermission();
// 切换权限模式
togglePermissionMode();
切换后会自动刷新页面,应用新的权限模式。
权限状态管理
权限相关的状态通过permissionStore进行管理,位于src/store/modules/permission.ts。
permissionStore核心状态
permissionStore定义了以下核心状态:
interface PermissionState {
// 权限代码列表
permCodeList: string[] | number[];
// 路由是否动态添加
isDynamicAddedRoute: boolean;
// 触发菜单更新的时间戳
lastBuildMenuTime: number;
// 后台菜单列表
backMenuList: Menu[];
// 前端菜单列表
frontMenuList: Menu[];
}
构建路由
buildRoutesAction是permissionStore中的核心函数,用于根据权限构建路由列表:
// src/store/modules/permission.ts
async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
// 根据不同的权限模式构建路由
// ...
}
该函数会根据当前的权限模式和用户角色,过滤出用户有权限访问的路由,并转换为菜单数据。
总结
vue-vben-admin的usePermission钩子为我们提供了一套完整而灵活的权限控制方案,通过角色和权限码的双重判断机制,可以满足各种复杂的权限需求。无论是简单的角色判断,还是复杂的权限码逻辑判断,usePermission都能轻松应对。
通过本文的介绍,相信你已经对usePermission的实现原理和使用方法有了深入的了解。在实际项目中,你可以根据需求选择合适的权限模式,并结合usePermission提供的API,快速实现从路由到按钮的全链路权限控制。
掌握usePermission,让权限控制变得简单而优雅,为你的项目保驾护航。
【免费下载链接】vue-vben-admin 项目地址: https://gitcode.com/gh_mirrors/vue/vue-vben-admin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



