前端学习之组件级权限控制(vue 版)

77 阅读3分钟

前端学习之组件级权限控制(vue 版)

一、组件级权限控制的内容

对于不同角色的用户,在同一个页面中,有不同的权限,比如:

功能显示状态的控制
  1. 普通用户只有搜索按钮,没有查看详情的按钮
  2. 管理员有编辑数据和删除数据的权限按钮
  3. 又或者管理员可以看到只有管理员才能看到的一个图表内容。
功能禁用状态的控制
  1. 普通用户能编辑表单中的部分数据,部分数据更新被禁用,而管理员能编辑所有数据。

组件级权限控制的实现方案

函数式权限控制

如通过 v-if="havePermission('sys:user:list')" 来控制组件的显示状态。 通过 :disabled="havePermission('sys:user:list')" 来控制组件的禁用状态。

指令式权限控制

这个属于面试常问的。

实际上核心就是 vue 的指令编写和 havePermission 函数

指令的编写:
局部指令

如果只是当前文件使用,可以直接定义在当前文件中,且需要在 setup 下面,且以 v 开头的驼峰式命名的变量

<script setup>
  // 在模板中启用 v-highlight
  const vHighlight = {
    mounted: el => {
      el.classList.add("is-highlight");
    },
  };
</script>

<template>
  <p v-highlight>This sentence is important!</p>
</template>
全局指令

如果不在当前文件内编写的话,需要进行全局注册指令

import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
app.directive("highlight", vHighlight);
app.mount("#app");
vue 指令和使用指令的组件的生命周期钩子执行顺序
  1. 组件的 setup
  2. 组件的 beforeCreate
  3. 组件的 created
  4. 组件的 beforeMounted
  5. 指令的 created
  6. 指令的 mounted:此时使用 el.remove 可以移除组件,但是组件内部代码仍然执行,包括 beforUnmounted
  7. 组件的 mounted

组件式权限控制

组件式权限控制的话,实际上将函数式权限控制和插槽封装在一起。

进阶功能,组件通过插槽作用域将权限控制交还给调用者使用
组件式权限控制代码
<template>
  <!-- 控制显隐,插槽作用域的数据提供给外部使用 -->
  <slot v-if="showSlot" :userPermission="permissions"></slot>
</template>

<script setup lang="ts">
  import { computed } from "vue";

  const props = defineProps({
    permission: { type: [String, Array] },
  });

  const permissions: any = []; // 用户具有的权限

  const showSlot = computed(() => {
    if (!props.permission) {
      //  没有传入权限,直接显示
      return true;
    }

    // 如果没有用户权限,直接不展示
    if (!permissions) {
      return false;
    }

    // 开始判断
    if (Array.isArray(props.permission)) {
      return props.permission.every((item: any) => permissions.includes(item));
    } else {
      return permissions.includes(props.permission);
    }
  });
</script>

<style scoped></style>
使用
<!-- 正常控制组件的显示状态 -->
<template>
  <Authority :permission="['sys:user:list']">
    <el-button>编辑</el-button>
  </Authority>
</template>
<!-- 手动控制权限的具体效果,插槽组件提供 userPermission ,将控制权交还给调用者 -->
<template>
  <div>
    <Authority :permission="['sys:user:list']">
      <template #default="{ userPermission }">
        <el-button :disabled="!userPermission.includes('sys:user:list')">编辑</el-button>
      </template>
    </Authority>
  </div>
</template>

什么情况下使用指令,什么情况下使用组件?

  1. 指令式权限控制 只影响组件元素的展示,不影响内部逻辑执行 还可以在外部通过 ref 引用,调用组件暴露的方法。

  2. 组件式权限控制的话,实际上将函数是权限控制和插槽封装在一起。

  3. 函数式权限控制,实际上就是通过 v-if,value 为执行一个判断是否有权限的函数。

什么时候使用指令?
  1. 按钮级别的 控制,或者一个元素级别的,无额外副作用的组件,比如组件内部不会自动请求数据,发送数据。
什么时候使用函数式权限控制或组件式权限控制?
  1. 都可以,看个人代码习惯。