网站首页 > 精选文章 正文
初识权限控制
刚开始学习 Vue 的时候,我克隆了一个 GitHub 上 star 最多的后台管理系统项目。第一次看到用自定义指令来控制按钮的显示隐藏时,觉得非常神奇又实用。
后来在工作中也一直沿用这种方式,无论是新项目还是接手别人的项目,都习惯性地使用权限指令来处理 UI 层面的权限控制。
vue
<!-- 示例:自定义权限指令 -->
<template>
<button v-auth="'user.create'">新增用户</button>
</template>
渐渐暴露的问题
但随着项目的深入和组件库的复杂化,权限指令的一些问题逐渐显现:
1.某些组件无法使用
比如在 element-plus 的 el-tooltip 上使用时会报错:
Runtime directive used on component with non-element root node.
这是因为该组件的根节点不是原生 DOM 元素,而是封装过的组件,导致指令无法正常绑定。
2.只能控制显示与否
- 想让无权限的按钮变为 disabled 或加个特殊样式?需要额外逻辑。
- 布局根据权限动态调整?还得配合条件渲染或类名切换。
- 更复杂的 UI 变化(如 tab 切换、菜单高亮)难以统一管理。
3.无法响应逻辑变化
权限不只是 UI 显示的问题,有时点击同一个按钮,不同角色执行的逻辑是不一样的:
ts
// 伪代码
function handleClick() {
if (hasPermission('admin')) {
doAdminAction();
} else {
doNormalAction();
}
}
这时候权限指令就无能为力了。
4.类型提示不友好(TS 环境下)
- 不传参数也不报错;
- 使用修饰符如 v-auth.any 时,TS 类型定义困难;
- 需要额外定义多个指令如 v-auth-any 才能实现功能。
转折点:React 中的启发
转头看看 React 是怎么做的?答案是——函数。
React 中没有指令这一说,权限判断通常是通过一个函数来完成的,例如:
tsx
if (can('user.create')) {
return <CreateUserButton />;
}
这种写法更灵活、更通用,而且可以在模板中也可以在逻辑中使用。
函数式权限控制
于是我在 Vue3 + TS 的项目中,尝试抛弃指令,改用一个统一的权限函数来处理所有权限判断。
定义权限函数
ts
// auth.ts
export function hasAuth(permission: string): boolean {
const permissions = useStore().state.user.permissions;
return permissions.includes(permission);
}
支持修饰符风格的写法:
ts
export function hasAuthAny(...permissions: string[]): boolean {
return permissions.some(hasAuth);
}
export function hasAuthAll(...permissions: string[]): boolean {
return permissions.every(hasAuth);
}
在组件中使用
vue
<script setup lang="ts">
import { hasAuth, hasAuthAny } from '@/utils/auth';
</script>
<template>
<div v-if="hasAuth('user.create')">
<button>新增用户</button>
</div>
<div v-if="hasAuthAny('user.edit', 'user.delete')">
<button v-if="hasAuth('user.edit')">编辑</button>
<button v-if="hasAuth('user.delete')">删除</button>
</div>
</template>
优势总结
功能 | 指令方式 | 函数方式 |
控制显示 | 好 | 好 |
控制禁用状态 | 需额外逻辑 | 直接调用 |
控制逻辑分支 | 差 | 好 |
支持组件嵌套 | 差 | 好 |
类型安全(TS) | 复杂 | 好 |
可复用性 | 指令分散 | 统一函数 |
推荐项目实践
如果你也在做后台管理系统,可以参考我的开源项目:
soon-admin-vue3
一套基于 Vue3 + TypeScript + Tailwind CSS 的全栈后台管理系统。
包含:
- 多语言 i18n 支持
- 多标签页管理
- 移动端适配
- 可视化 Mock 数据服务 soon-mock
- 类型安全工具链 soon-tools / soon-i18n / soon-fetch 等
猜你喜欢
- 2025-06-13 前端必看!7 个 Vue3 性能优化实战技巧,让页面飞起来
- 2025-06-13 前端也能玩转截图?uni-app + Vue3 实现页面快照功能
- 2025-06-13 Vue2 升级 Vue3 一文通关(vue-cli2.0升级3.0)
- 2025-06-13 Vue2的16种传参通信方式(vue有几种传参方式)
- 2025-06-13 面试官:聊聊你知道的Vue与React的区别
- 2025-06-13 vue3.0总结之ref与reactive(vue ref reactive)
- 2025-06-13 90% 的前端工程师都不知道的 Vue3 实战神操作,看完直呼后悔没早学
- 2025-06-13 vue3 组件初始化流程(vue组件初始化顺序)
- 2025-06-13 从 React 过渡到 Vue 3:开发者的实践指南
- 2025-06-13 vue重定向(vue重定向后403报错)
- 最近发表
- 标签列表
-
- 向日葵无法连接服务器 (32)
- git.exe (33)
- vscode更新 (34)
- dev c (33)
- git ignore命令 (32)
- gitlab提交代码步骤 (37)
- java update (36)
- vue debug (34)
- vue blur (32)
- vscode导入vue项目 (33)
- vue chart (32)
- vue cms (32)
- 大雅数据库 (34)
- 技术迭代 (37)
- 同一局域网 (33)
- github拒绝连接 (33)
- vscode php插件 (32)
- vue注释快捷键 (32)
- linux ssr (33)
- 微端服务器 (35)
- 导航猫 (32)
- 获取当前时间年月日 (33)
- stp软件 (33)
- http下载文件 (33)
- linux bt下载 (33)