实现前端按钮级别 RBAC 权限控制的核心要点
1.权限状态管理(全局存储)
将后端返回的权限码存入 Pinia/Vuex,提供统一的权限判断方法;
js
//stores/permission.ts
import { defineStore } from 'pinia'
export const usePermissionStore = defineStore('permission', {
state: () => ({
// 存储当前用户的所有权限码
permissionCodes: [] as string[]
}),
actions: {
// 初始化权限码(登录后调用)
setPermissionCodes(codes: string[]) {
this.permissionCodes = codes
},
// 核心方法:判断是否拥有某个权限
hasPermission(code: string) : boolean {
// 超级管理员默认拥有所有权限(可选)
if (this.permissionCodes.includes('admin')) return true
return this.permissionCodes.includes(code)
}
}
})
2.封装权限指令
通过自定义v-permission指令快速实现按钮的显示 / 隐藏 / 禁用,降低业务代码耦合;
js
//directives/permission.ts
import { usePermissionStore } from "@/stores/permission";
// 注册自定义指令:v-permission,用于控制元素的显示与隐藏
// 默认导出一个函数,接收Vue应用实例作为参数
export default function setupPermissionDirective(app: any) {
app.directive('permission', { // 指令名称为permission。vue会自动加上"v-"前缀,在vue中使用时为v-permission
mounted(el: HTMLElement, binding: any) { // 指令挂载时的钩子函数,el为绑定指令的元素,binding为指令的绑定信息
const { value: permissionCode } = binding;
const permissionStore = usePermissionStore();
// 如果没有传入权限码,默认不显示该元素
if(!permissionCode) {
el.style.display = 'none';
return;
}
// 检查权限,没有权限则移除元素
if (permissionCode && !permissionStore.hasPermission(permissionCode)) {
el.parentNode && el.parentNode.removeChild(el);
}
}
});
}
在main.ts中注册全局指令
js
//main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
// 引入权限指令
import setupPermissionDirective from './directives/permission'
const app = createApp(App)
app.use(createPinia())
// 注册权限指令
setupPermissionDirective(app)
app.mount('#app')
3.业务中使用
(前后端配合):前端控制展示,后端校验接口权限,避免权限绕过。
js
<script setup lang="ts">
import {ElButton} from 'element-plus';
import { usePermissionStore } from './stores/permission';
const permissionStore = usePermissionStore();
// 模拟登录,设置用户权限
permissionStore.setPermissionCodes(['btn:user:add', 'btn:user:edit']);
// permissionStore.setPermissionCodes(['btn:user:add', 'btn:user:edit', 'btn:user:delete']);
</script>
<template>
<div class="user-actions">
<!-- 有"btn:user:add"权限才显示新增按钮 -->
<el-button v-permission="'btn:user:add'" type="primary">新增用户</el-button>
<!-- 有"btn:user:edit"权限才显示编辑按钮 -->
<el-button v-permission="'btn:user:edit'">编辑用户</el-button>
<!-- 有"btn:user:delete"权限才显示删除按钮 -->
<el-button v-permission="'btn:user:delete'">删除用户</el-button>
</div>
</template>
<style scoped></style>
大白话:用户登录后,后端返回该用户的所有权限,如编辑,添加,删除等,前端存储用户权限列表到pinia中,并提供提供统一的权限判断方法hasPermission。
前端封装自定义指令,v-permission实现按钮的显示/隐藏,判断如果元素绑定的指令在用户权限列表里,则显示,否则隐藏。
前端在元素上使用v-permission绑定自定义指令,控制按钮的显示与隐藏。