vue3自定义指令——权限

433 阅读1分钟

我们来实现一个自定义权限指令来控制元素动态显示、隐藏, 详细代码可查看sable。这里只列出了主要的代码

自定义权限指令

permission.ts

import type { App } from "vue"
import { ref, watchEffect } from "vue"

import { storeToRefs } from "pinia"
import { usePermissionStore } from "@/store/usePermissionStore.ts"

// 按钮权限
export function registerPermission(app: App) {
  const { permissions } = storeToRefs(usePermissionStore())

  app.directive("permission", {
    created(el: HTMLButtonElement, binding) {
      const { value } = binding

      const buttonPermission = Array.isArray(value) ? value : [value]
      const visible = ref(false)

      watchEffect(() => {
        visible.value = hasIntersection(permissions, buttonPermission)
        el.style.display = visible.value ? "" : "none"
      })
    },
  })
}

function hasIntersection(permissions: Ref<string[]>, arr2: string[]) {
  const map = new Map()
  permissions.value.forEach((item) => map.set(item, true))
  return arr2.some((item) => map.get(item))
}

权限 store

usePermissionStore.ts

import { defineStore } from "pinia"

export const usePermissionStore = defineStore("permission", {
  state: () => ({
    permissions: [],
  }),
  getters: {},
  actions: {
    setPermissions(permissions: string[]) {
      this.permissions = permissions
    },
  },
})

使用

permission.vue

<script lang="ts" setup>
  import { storeToRefs } from "pinia"

  const userPermissionStore = usePermissionStore()
  const { setPermissions } = userPermissionStore
  const { permissions } = storeToRefs(userPermissionStore)
</script>

<template>
  <div>
    自定义指令

    <n-divider title-placement="left"> 根据权限列表来展示 </n-divider>
    <div>
      <n-space>
        <n-button @click="setPermissions(['read'])"> 设置为只有阅读权限 </n-button>
        <n-button @click="setPermissions(['read', 'write'])"> 设置为阅读和修改权限 </n-button>
      </n-space>
    </div>
    <div mt-4>
      权限列表: {{ permissions }}
      <n-button v-permission="'read'"> 阅读 </n-button>
      <n-button v-permission="'write'"> 写入 </n-button>
    </div>
  </div>
</template>

<style></style>

效果

vue-permission.gif