Vue3自定义指令 html 元素级别的鉴权

文章介绍了在Vue3中如何改造生命周期钩子,并利用这些钩子进行权限管理。通过在前端获取并存储操作权限数据,结合vue-router的路由守卫,实现了在进入指定路由前的权限校验。此外,还详细展示了如何创建一个自定义指令,用于动态控制按钮、链接等元素的展示和禁用状态,以及提供权限提示功能。

Vue3 改造后的生命周期钩子变成了七个,而且名称变得比较好记了。

在这里插入图片描述

前端获取到操作权限数据之后,进行转换并存储在sessionStorage中,转换后的权限数据大概如下

{
   
   
  "UserMgr": ["add", "edit"],
  "RoleMgr": ["add", "edit"]
}

通过 vue-router 的路由守卫,在进入指定的路由前先获取to路由的路由名,然后存储在localStorage中
自定义指令先从localStorage中获取to路由名,然后通过这个to路由名,找到对应的功能权限标识
自定义指令将第 2 步获取到操作权限标识数组和传入的操作权限标识比较,有相同的值,则有权限,否则表示没有权限

<script lang="ts">
export default {
   
   
  name: 'PermissionDirective01',
}
</script>
<script setup lang="ts">
import {
   
    ElMessage } from 'element-plus'
import {
   
    Directive, nextTick, ref } from 'vue'
import MyButton from './MyButton.vue'

let hasPermissions = ref<string[]>([])
interface CustomHTMLElement extends HTMLElement {
   
   
  _clickCall?: (evt: MouseEvent) => boolean | undefined
  // 存储原始的display方式
  originalDisplay?: string
}
function doPermissionValidate(el: CustomHTMLElement, permissionFlag: string, arg: string) {
   
   
  let clickCall = el._clickCall as (evt: MouseEvent) => boolean | undefined
  if (!clickCall) {
   
   
    /**
     * 自定义的点击事件必须在一开始的时候就添加上去,保证鉴权事件在所有事件之前
     *
     */
    clickCall = (evt: MouseEvent) => {
   
   
      if (hasPermissions.value.indexOf(permissionFlag) < 0) {
   
   
        /*
        阻止事件冒泡且同时阻止同类事件的触发(如:原本可能绑定了多个click事件,
        stopImmediatePropagation执行之后能确保当前click事件之后的其他click事件都不会被触发)
         */
        evt.stopImmediatePropagation()
        evt.stopPropagation()
        evt.preventDefault()
        if (arg === 'tips') {
   
   
          ElMessage({
   
   
            showClose: true,
            message: '没权限执行该操作',
            type: 'warning',
          })
        }
        return false
      }
    }
    el.addEventListener('click', clickCall, false)
    el._clickCall = clickCall
  }
  if (hasPermissions.value.indexOf(permissionFlag) < 0) {
   
   
    // 之所以在nextTick中执行,是为了解决el-button这种UI库组件,样式设置不上去的问题
    nextTick(() => {
   
   
      if (!el.classList.contains('is-disabled')) {
   
   
        el.classList.add('is-disabled')
      }
    })
    switch (arg) {
   
   
      case 'hidden': {
   
   
        el.originalDisplay = el.style.display
        el.style.display = 'none'
        break
      }
      case 'disabled': {
   
   
        // 之所以在nextTick中执行,是为了解决el-button这种UI库组件,属性设置不上去的问题
        nextTick(() => {
   
   
          el
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值