Skip to content

用户权限控制的实现

在Web开发中,用户权限一般分为两种:页面权限按钮权限

页面权限也就是页面菜单,通过后端和vue-router就很容易实现,这里就不赘述了。

按钮权限,也可以说是页面元素权限,比如一个按钮、一个表单、一个查询结果等,这些元素是否要显示,都可以通过权限控制。

本文将介绍如何通过 自定义指令组件封装 两种方式来实现 按钮权限控制

自定义指令

自定义指令是一种轻量级的方式,可以直接控制 DOM 元素的显示或隐藏。

1. 指令代码

ts
import { Directive } from 'vue';

interface PermissionOptions {
  value: string | string[];
}

const hasPermission = (permissions: string[], required: string | string[]) => {
  if (Array.isArray(required)) {
    return required.some((perm) => permissions.includes(perm));
  }
  return permissions.includes(required);
};

const permission: Directive = {
  mounted(el, binding) {
    const userPermissions = ['view', 'edit', 'delete']; // 模拟用户拥有的权限数据
    const { value }: PermissionOptions = binding;
    if (!hasPermission(userPermissions, value)) {
      // 移除dom
      el.parentNode && el.parentNode.removeChild(el);
    }
  },
};

export default permission;

2. 注册指令

在项目的入口文件中进行全局注册:

ts
import { App } from 'vue';
import permission from './directives/permission';

export function registerDirectives(app: App) {
  app.directive('permission', permission);
}

3. 使用指令

在组件中使用:

vue
<template>
  <div>
    <button v-permission="'edit'">编辑</button>
    <button v-permission="['view', 'delete']">查看或删除</button>
  </div>
</template>

跳转到 Vue演练场 查看效果。

4. 优点和缺点

优点

  1. 轻量化:无需额外的组件封装,直接操作 DOM,性能较好。
  2. 灵活:可以轻松结合任何组件或 HTML 元素使用。

缺点

  1. 难以复用复杂逻辑:如需要进行复杂的渲染逻辑,自定义指令可能显得局限。
  2. 难以测试:DOM 操作逻辑难以进行单元测试。
  3. 内存泄漏:只是移出了组件的DOM,并没有真正销毁组件,可能会导致一些问题。

可以查看 远方 大佬的视频讲解:抖音: 自定义指令控制权限的弊端

组件封装

通过封装组件,可以在模板中以声明式的方式实现权限控制,同时支持插槽功能。

1. 实现代码

vue
<template>
  <slot v-if="isAllowed"></slot>
</template>

<script setup lang="ts" name="PermissionCom">
import { defineComponent, computed, PropType } from 'vue';

const props = defineProps<{
  permission: string | string[]
}>()

// 这个值可以从store中取
const userPermissions = ['edit', 'view', 'delete']

const isAllowed = computed(() => {
  const { permission } = props;
  if (Array.isArray(permission)) {
    return permission.some((perm) => userPermissions.includes(perm));
  }
  return userPermissions.includes(permission);
})
</script>

2. 使用组件

vue
<template>
  <div>
    <Permission permission="edit">
      <button>编辑</button>
    </Permission>
    <Permission :permission="['view', 'delete']">
      <button>查看或删除</button>
    </Permission>
  </div>
</template>

<script setup lang="ts" name="PermissionExample">
import Permission from '@/components/Permission.vue';
</script>

跳转到 Vue演练场 查看效果。

3. 优点和缺点

优点

  1. 可复用性强:通过组件封装,可以更容易地在项目中统一管理权限逻辑。
  2. 测试友好:组件逻辑易于单元测试,适合复杂的业务场景。
  3. 支持插槽:可以对渲染内容进行灵活的控制。

缺点

  1. 性能开销略高:每次渲染都会创建组件实例。
  2. 模板冗长:相比指令方式,模板代码显得稍长。