说说Vue怎么实现权限管理?控制到按钮级别的权限怎么做?

4 阅读2分钟

权限管理是 B 端系统中非常常见、但又容易出坑的模块。


一、权限管理核心思路🧠

权限控制通常包括三类:

权限类型举例控制方式
路由权限页面级访问(如 /admin)路由守卫(beforeEach)
组件权限页面中的某个功能区块v-if、组件显示与否
按钮权限新增/编辑/删除按钮自定义指令控制显示 / 禁用

二、按钮级权限控制的实现方案📦

常见做法:基于指令(v-permission)

你可以封装一个指令,判断当前用户是否具备某权限:

1)定义权限指令

// directives/permission.ts
import { DirectiveBinding } from 'vue'
import { useUserStore } from '@/stores/user'

export default {
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    const userStore = useUserStore()
    const permission = binding.value

    if (!userStore.permissions.includes(permission)) {
      el.parentNode && el.parentNode.removeChild(el)
    }
  }
}

2)注册全局指令

// main.ts
import permission from '@/directives/permission'
app.directive('permission', permission)

3)使用方式

<!-- 只有有 'user:add' 权限才显示 -->
<el-button v-permission="'user:add'">新增用户</el-button>

三、用户权限的来源 🧰

在项目中通常有几种方式获取当前用户权限:

来源举例
登录返回的用户权限码列表如:[‘user:add’, ‘user:edit’]
后台返回的菜单结构中嵌套权限菜单中含按钮权限字段
动态角色切换后更新权限列表Admin / 普通用户 等切换场景

四、配合组件逻辑封装权限判断工具函数 🧩

// utils/permission.ts
export function hasPermission(code: string) {
  const userStore = useUserStore()
  return userStore.permissions.includes(code)
}

用在业务中:

<el-button v-if="hasPermission('user:delete')">删除</el-button>

<template>
  <div>
    <el-button v-permission="'patient:add'">新增患者</el-button>
    <el-button v-if="hasPermission('patient:edit')">编辑</el-button>
    <el-button :disabled="!hasPermission('patient:export')">导出数据</el-button>
  </div>
</template>

五、最佳实践总结 ✨

建议原因
权限控制逻辑统一放到指令 / 方法中避免业务中到处写重复逻辑
尽量控制在 DOM 层(隐藏/禁用)安全性更高,避免误操作
后台接口也要二次校验权限前端控制 ≠ 安全控制
权限码统一管理为常量 or 枚举避免写错权限码(如 USER_ADD)

总结 🔚

  • 按钮权限推荐使用指令 + 用户权限列表来控制;
  • 提前在登录后拿到权限列表,保存在 Pinia;
  • 页面中使用 v-permission 或 hasPermission() 函数判断是否可见;
  • 可以扩展为禁用、隐藏、弹提示等多种行为;
  • 后端配合更安全可靠,前后双重校验。