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 获取用户权限)。
相关推荐
q***498620 分钟前
MySQL数据的增删改查(一)
android·javascript·mysql
我有一个object21 分钟前
uniapp上传文件报错:targetSdkVersion设置>=29后在Android10+系统设备不支持当前路径。请更改为应用运行路径!
前端·javascript·vue.js·uniapp
北极糊的狐25 分钟前
关于jQuery 事件绑定,记录常用事件类型及核心注意事项
前端·javascript·jquery
星空的资源小屋27 分钟前
极速精准!XSearch本地文件搜索神器
javascript·人工智能·django·电脑
_Kayo_31 分钟前
vue3 computed 练习笔记
前端·vue.js·笔记
CodeSheep35 分钟前
VS 2026 正式发布,王炸!
前端·后端·程序员
无奈何杨35 分钟前
CoolGuard事件查询增加策略和规则筛选,条件结果展示
前端·后端
梦里不知身是客1138 分钟前
正则表达式常见的介绍
前端·javascript·正则表达式
初学小白...1 小时前
HTML知识点
前端·javascript·html
鹏多多1 小时前
flutter睡眠与冥想数据可视化神器:sleep_stage_chart插件全解析
android·前端·flutter