vue自定义“权限控制”指令

自定义指令示例:权限控制指令 v-permission

场景说明

实现一个根据用户权限动态控制元素显示/隐藏或禁用操作的指令,支持以下功能:

  1. 根据权限列表隐藏无权限的元素。
  2. 可选禁用元素而非隐藏(如按钮变灰)。
  3. 权限变更时自动更新元素状态。

完整代码与逐行解析

ini 复制代码
// permissionDirective.js
export default {
  // 元素挂载或更新时触发
  mounted(el, binding) {
    updateElementPermission(el, binding);
  },
  // 绑定值或参数变化时触发
  updated(el, binding) {
    updateElementPermission(el, binding);
  },
};

// 统一处理权限逻辑
function updateElementPermission(el, binding) {
  // 1. 获取必要数据
  const { value, modifiers, arg } = binding;
  const hasPermission = checkPermission(value); // 核心权限校验

  // 2. 处理无权限的情况
  if (!hasPermission) {
    // 禁用模式(通过参数指定,如 v-permission:disable)
    if (arg === 'disable') {
      el.disabled = true; // 禁用表单元素
      el.style.opacity = '0.5'; // 视觉提示
      el.title = '无权限操作'; // 鼠标悬停提示
    } 
    // 默认隐藏模式
    else {
      el.style.display = 'none'; // 直接隐藏元素
    }
  }
  // 3. 处理有权限的情况(恢复初始状态)
  else {
    // 禁用模式的恢复
    if (arg === 'disable') {
      el.disabled = false;
      el.style.opacity = '1';
      el.title = '';
    } 
    // 隐藏模式的恢复
    else {
      el.style.display = '';
    }
  }

  // 4. 支持强制显示(通过修饰符,如 v-permission.force)
  if (modifiers.force) {
    el.style.display = '';
    el.disabled = false;
  }
}

// 模拟权限校验(实际从 Vuex/Pinia 获取)
function checkPermission(requiredPermission) {
  // 实际项目中从全局状态获取用户权限
  const userPermissions = ['view', 'edit'];
  return userPermissions.includes(requiredPermission);
}

逐行代码解析

1. 指令生命周期处理

scss 复制代码
export default {
  mounted(el, binding) { // 元素挂载时初始化
    updateElementPermission(el, binding);
  },
  updated(el, binding) { // 绑定值变化时更新
    updateElementPermission(el, binding);
  },
};
  • 关键点‌:

    • mounted:元素首次插入 DOM 时校验权限。
    • updated:当指令绑定的值(如权限要求)或参数变化时重新校验。

‌**2. 统一处理函数 updateElementPermission**‌

javascript 复制代码
function updateElementPermission(el, binding) {
  const { value, modifiers, arg } = binding;
  const hasPermission = checkPermission(value);
  // ...
}
  • 解构赋值‌:

    • value:指令绑定的值,如 v-permission="'edit'" 中的 'edit'
    • modifiers:修饰符对象,如 .force 对应 modifiers.force: true
    • arg:指令参数,如 :disable 对应 arg: 'disable'

3. 权限校验逻辑

ini 复制代码
function checkPermission(requiredPermission) {
  const userPermissions = ['view', 'edit'];
  return userPermissions.includes(requiredPermission);
}
  • 模拟数据‌:实际项目中需从全局状态(如 Vuex)获取用户权限列表。
  • 返回值‌:当前用户是否拥有所需权限。

4. 无权限处理 - 禁用模式

ini 复制代码
if (arg === 'disable') {
  el.disabled = true; // 适用于按钮、输入框等
  el.style.opacity = '0.5'; // 视觉提示
  el.title = '无权限操作'; // HTML 原生属性提示
}
  • 适用场景‌:允许用户看到元素但无法交互(如灰色按钮)。

  • 细节‌:

    • el.disabled 仅对表单元素有效,普通元素需用 CSS 或事件拦截。

5. 无权限处理 - 默认隐藏模式

arduino 复制代码
else {
  el.style.display = 'none'; // 彻底隐藏元素
}
  • 优势‌:完全移除元素对布局的影响。
  • 注意 ‌:若元素含动画,可用 visibility: hidden + opacity: 0 代替。

6. 权限恢复处理

ini 复制代码
else {
  if (arg === 'disable') {
    el.disabled = false;
    el.style.opacity = '1';
    el.title = '';
  } else {
    el.style.display = '';
  }
}
  • 恢复逻辑 ‌:重置元素到初始状态,display: '' 会恢复为 CSS 定义的值。

7. 强制显示模式

ini 复制代码
if (modifiers.force) {
  el.style.display = '';
  el.disabled = false;
}
  • 用途 ‌:开发阶段临时覆盖权限控制,如 v-permission.force
  • 扩展性 ‌:可结合环境变量自动启用(如 process.env.NODE_ENV === 'development')。

高级使用示例

场景1:禁用无权限的删除按钮

ini 复制代码
<template>
  <button 
    v-permission:disable="'delete'"
    @click="handleDelete"
  >删除数据</button>
</template>
  • 效果 ‌:用户无 delete 权限时按钮变灰且提示。

场景2:动态切换权限

xml 复制代码
<template>
  <div>
    <button @click="togglePermission">切换权限</button>
    <p v-permission="requiredPermission">需要{{ requiredPermission }}权限的内容</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      requiredPermission: 'edit'
    };
  },
  methods: {
    togglePermission() {
      this.requiredPermission = this.requiredPermission === 'edit' ? 'view' : 'edit';
    }
  }
};
</script>
  • 动态响应‌:点击按钮切换所需权限,指令自动更新元素状态。

对比其他实现方案

方案 优点 缺点
自定义指令 逻辑复用,统一管理 需处理全局状态访问
组件封装 可复用带权限控制的组件 每个需控制的组件都要封装
v-if + 计算属性 简单场景直观 重复代码多,难以统一修改逻辑

总结

  • 核心价值‌:通过指令集中处理权限逻辑,避免重复代码。

  • 扩展性 ‌:通过参数(:disable)和修饰符(.force)支持多样化需求。

  • 响应式‌:利用 Vue 的响应式系统,权限变化时自动更新元素状态。

  • 注意事项‌:

    • 普通元素禁用需手动拦截事件(如添加 @click.stop)。
    • 实际项目需接入全局权限状态(如从 Vuex 获取用户权限)。
相关推荐
崔庆才丨静觅3 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅25 分钟前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment1 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅1 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊1 小时前
jwt介绍
前端
爱敲代码的小鱼1 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
吹牛不交税2 小时前
admin.net-v2 框架使用笔记-netcore8.0/10.0版
vue.js·.netcore
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc
NEXT062 小时前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法