Skip to content

组件权限校验

按钮权限

按钮级别权限可以使用 自定义指令 来实现,全局注入自定义指令:

vue
<template>
  <a-button type="primary" v-auth="true">有权限按钮</a-button>
  <a-button type="primary" v-auth="false">无权限按钮</a-button>
</template>

<script setup lang="ts">
  import {Button as AButton} from 'ant-design-vue'
</script>
ts
const app = createApp(App)

app.directive("auth", {
  mounted: (el, binding) => {
    // 类型判断,规定权限校验的值必须为 boolean 类型
    // 也可以按照用户角色,判断按钮/组件是否拥有权限
    if (typeof binding.value === "boolean") {
      if (!binding.value) {
        el.style.display = "none";
      }
    }
  }
})

组件权限

组件的权限校验需要注意:如果用 v-auth 自定义指令控制其显示或隐藏,虽然隐藏了组件,但是组件的生命周期函数还是会执行的!

看下面的示例:

vue
<template>
  <a-button type="primary" @click="handleClick">有权限按钮</a-button>
  <!--  组件没权限,已经不显示了 -->
  <HelloWorld ref="helloRef" v-auth="false"/>
</template>

<script setup lang="ts">
  import {ref} from "vue";
  import {Button as AButton} from 'ant-design-vue'
  import HelloWorld from "./components/HelloWorld.vue";

  const helloRef = ref(null)

  function handleClick() {
    helloRef.value?.change(); // 该方法仍然会触发
  }
</script>
vue
<template>
<div class="my-table">
  <a-table
   :columns="columns"
   :data-source="data"
   :pagination="false"
   :bordered="true"/>
  </div>
</template>

<script setup lang="ts">
  import {onMounted} from "vue";
  import {Table as ATable} from 'ant-design-vue'

  const columns = [
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
      align: 'center',
    },
    {
      title: '年龄',
      dataIndex: 'age',
      key: 'age',
      align: 'center',
    }
  ];

  const data = [
    {
      key: '1',
      name: '王一博',
      age: 32,
    },
    {
      key: '2',
      name: '陈伟霆',
      age: 42,
    }
  ];

  onMounted(() => {
    console.log("onMounted组件触发")
  })

  function change() {
    console.log("change点击")
  }

  defineExpose({
    change
  })
</script>

<style scoped>
  .my-table {
    width: 400px;
    margin-top: 10px;
  }
</style>

注意

上面的示例中,虽然 v-auth="false" 表示组件没有权限已经隐藏了,但是 <HelloWorld /> 中的 onMounted 生命周期和 defineExpose 暴漏的方法仍然可以被触发!

解决方案:

新增 <Authority> 组件,该组件有一个默认插槽,通过 v-if 判断插槽内容是否有权限显示。

vue
<template>
	<slot v-if="hasPermission()"></slot>
</template>

<script setup lang="ts">
  const props = defineProps(['auth'])

  function hasPermission() {
    // 权限校验工作...
    return ['admin'].includes(props.auth)
  }
</script>
vue
<template>
  <a-button type="primary" @click="handleClick">有权限按钮</a-button>

	<!-- auth属性传递当前用户角色 -->
  <Authority auth="user">
    <HelloWorld ref="helloRef" />
  </Authority>
</template>

<script setup lang="ts">
  import {ref} from "vue";
  import {Button as AButton} from 'ant-design-vue'
  import HelloWorld from "./components/HelloWorld.vue";
  import Authority from "./components/Authority.vue";

  const helloRef = ref(null)

  function handleClick() {
    helloRef.value?.change();
  }
</script>

Released under the MIT License.