企业项目管理、ORK、研发管理与敏捷开发工具平台

网站首页 > 精选文章 正文

从权限指令到函数式鉴权:Vue 权限控制的进化之路

wudianyun 2025-06-13 17:21:20 精选文章 4 ℃

初识权限控制

刚开始学习 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 等

Tags:

最近发表
标签列表