用户权限控制的实现 
在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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2. 注册指令 
在项目的入口文件中进行全局注册:
ts
import { App } from 'vue';
import permission from './directives/permission';
export function registerDirectives(app: App) {
  app.directive('permission', permission);
}1
2
3
4
5
6
2
3
4
5
6
3. 使用指令 
在组件中使用:
vue
<template>
  <div>
    <button v-permission="'edit'">编辑</button>
    <button v-permission="['view', 'delete']">查看或删除</button>
  </div>
</template>1
2
3
4
5
6
2
3
4
5
6
跳转到 Vue演练场 查看效果。
4. 优点和缺点 
优点
- 轻量化:无需额外的组件封装,直接操作 DOM,性能较好。
 - 灵活:可以轻松结合任何组件或 HTML 元素使用。
 
缺点
- 难以复用复杂逻辑:如需要进行复杂的渲染逻辑,自定义指令可能显得局限。
 - 难以测试:DOM 操作逻辑难以进行单元测试。
 - 内存泄漏:只是移出了组件的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>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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>1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
跳转到 Vue演练场 查看效果。
3. 优点和缺点 
优点
- 可复用性强:通过组件封装,可以更容易地在项目中统一管理权限逻辑。
 - 测试友好:组件逻辑易于单元测试,适合复杂的业务场景。
 - 支持插槽:可以对渲染内容进行灵活的控制。
 
缺点
- 性能开销略高:每次渲染都会创建组件实例。
 - 模板冗长:相比指令方式,模板代码显得稍长。