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 获取用户权限)。
相关推荐
weixin_382395232 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__2 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.3 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~4 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华4 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子7 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅7 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni7 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学8 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端