Skip to content

🔐 v-auth 权限控制指令

🎯 功能简介

v-auth 指令用于基于用户权限控制 UI 元素的显示与隐藏,是构建权限管理系统的核心组件之一。当用户没有特定权限时,带有该指令的元素将被自动从 DOM 中移除。

🚀 使用方法

基本用法

vue
<!-- 单个权限控制 -->
<button v-auth="'user-add'">添加用户</button>

<!-- 多权限控制(需同时满足所有权限) -->
<button v-auth="['user-edit', 'user-delete']">高级操作</button>

⚠️ 注意事项

  1. 指令只在元素挂载时执行一次,不会响应权限数据的动态变化
  2. 元素一旦被移除就不会自动恢复,即使后续获得了相应权限
  3. 权限值通常使用 模块-操作 的格式,例如:user-addreport-export

📝 完整示例

下面是一个交互式的权限控制演示组件:

vue
<template>
    <div>
      <h2>权限指令演示</h2>
      
      <section class="auth-control">
        <h3>权限控制</h3>
        <div>
          <label>当前路由: {{ authStore.routeName }}</label>
          <div class="permission-panel">
            <h4>为当前页面添加权限:</h4>
            <div>
              <input v-model="newPermission" placeholder="输入新权限" />
              <button @click="addPermission">添加</button>
            </div>
            <div>
              <p class="lh-32px">1. 指令只在元素挂载时执行,暂时不会响应权限数据的变化,<br>
                2. 元素一旦被移除就永久消失,即使后来有了权限也不会自动恢复,后续确实有这样的场景我可以改造指令,<br>
                暂时没有动态变化的场景</p>
            </div>
            <div class="permission-list">
              <span v-for="perm in currentPermissions" :key="perm" class="permission-tag">
                {{ perm }}
                <button @click="removePermission(perm)">×</button>
              </span>
            </div>
          </div>
        </div>
      </section>
      
      <section class="auth-test">
        <h3>指令测试</h3>
        
        <!-- 需要 add 权限 -->
        <div>
          <button v-auth="'auth-add'" class="auth-btn">添加按钮 (需要 "add" 权限)</button>
        </div>
        
        <!-- 需要 edit 权限 -->
        <div>
          <button v-auth="'auth-edit'" class="auth-btn">编辑按钮 (需要 "edit" 权限)</button>
        </div>
        
        <!-- 需要 delete 权限 -->
        <div>
          <button v-auth="'auth-delete'" class="auth-btn">删除按钮 (需要 "delete" 权限)</button>
        </div>
        
        <!-- 需要同时拥有 edit 和 delete 权限 -->
        <div>
          <button v-auth="['auth-edit', 'auth-delete']" class="auth-btn">高级操作 (需要 "edit" 和 "delete" 权限)</button>
        </div>
      </section>
    </div>
  </template>
  
  <script setup>
  import { ref, computed } from 'vue';
  import { AuthStore } from '@/index';
  
  const authStore = AuthStore();
  const newPermission = ref('');
  
  // 获取当前页面的权限列表
  const currentPermissions = computed(() => {
    return authStore.authButtonList[authStore.routeName] || [];
  });
  
  // 添加权限
  function addPermission() {
    if (!newPermission.value) return;
    
    // 深拷贝当前权限列表
    const updatedAuthList = JSON.parse(JSON.stringify(authStore.authButtonList));
    
    // 确保当前路由的权限数组存在
    if (!updatedAuthList[authStore.routeName]) {
      updatedAuthList[authStore.routeName] = [];
    }
    
    // 添加新权限(如果不存在)
    if (!updatedAuthList[authStore.routeName].includes(newPermission.value)) {
      updatedAuthList[authStore.routeName].push(newPermission.value);
      authStore.authButtonList = updatedAuthList;
    }
    
    newPermission.value = '';
  }
  
  // 移除权限
  function removePermission(perm) {
    const updatedAuthList = JSON.parse(JSON.stringify(authStore.authButtonList));
    
    if (updatedAuthList[authStore.routeName]) {
      const index = updatedAuthList[authStore.routeName].indexOf(perm);
      if (index !== -1) {
        updatedAuthList[authStore.routeName].splice(index, 1);
        authStore.authButtonList = updatedAuthList;
      }
    }
  }
  </script>
  
  <style>
  .auth-control, .auth-test {
    margin-bottom: 30px;
    padding: 20px;
    border: 1px solid #eee;
    border-radius: 4px;
  }
  
  .permission-panel {
    margin-top: 15px;
  }
  
  .permission-list {
    margin-top: 10px;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }
  
  .permission-tag {
    display: inline-flex;
    align-items: center;
    background: #f2f2f2;
    padding: 5px 10px;
    border-radius: 4px;
  }
  
  .permission-tag button {
    background: none;
    border: none;
    color: #ff4d4f;
    cursor: pointer;
    margin-left: 5px;
  }
  
  .auth-btn {
    margin: 10px 0;
    padding: 10px 15px;
    background: #1890ff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }
  </style>

🖼️ 效果预览

下图展示了权限指令的实际效果,您可以动态添加或移除权限来观察元素的显示和隐藏:

v-auth 指令效果

🔗 与权限系统集成

v-auth 指令会自动从 AuthStore 中获取当前用户的权限数据,无需手动传递。权限数据通常在用户登录后由后端接口返回,并存储在 AuthStore 中。

💡 最佳实践

  • 将权限代码按业务模块分类,例如 user-addreport-export
  • 对安全敏感的操作使用多权限组合,如 ['user-delete', 'admin-role']
  • 在路由层面也配置相应的权限控制,防止直接访问URL绕过前端权限检查
  • 权限名称保持一致性,推荐使用 模块-操作 的命名方式

🔗 相关资源

Released under the MIT License.