vue权限控制的想法

前言

最近做到了一个权限控制的功能。在这个功能中看到了这个功能的写法,了解到了这个权限控制的功能,也引发了思考。除了 v-if ,还有没有更好的,更直观的,更全局的写法呢?带着这个问题,我们先来看一下,这个权限数据的来源。

权限来源

获取数据的方法也很简单,就是后台接口请求数据。后端在登录后一次性返回所有的权限数据,然后全局 localStorage 或者 store 存储起来。如果发生了修改就可以及时的通知到全局,在使用获取的时候也方便快捷。代码如下:

import { defineStore } from 'pinia'
// 声明,初始化
const defaultState = {
  permissions: {}, // 权限列表
}

// 设置state,存储
function setData(obj) {
  Object.keys(obj).forEach((key) => {
    state[key] = obj[key]
  })
  // 每次改动更新缓存
  localStorage.setItem(LOCAL_STORAGE_NAME, JSON.stringify(toRaw(state)))
}

// 请求权限码
async function getPermissionList() {
  const res = await ajaxStore.common.getPermissionList()
  if (res.data?.code === '0') {
    const arr = res.data?.data ?? []
    const obj = {}
    arr.forEach((item) => (obj[item.permissionCode] = item.permissionName))
    // 全局存储
    setData({ permissions: obj })
    return state.permissions
  } else {
    return null
  }
}

获取到数据以后,就可以来思考怎么使用这些数据。目前,所知的有3种权限控制方式,下面我们一个一个的来看。

三种方法

1. 函数方式

这是我们最先想到的方法,也是最常用的方法。代码如下:

<template>
  <div>
    <Tabs :data="tabConfigs"></Tabs>
    <NoPower v-if="!(tabConfigs && tabConfigs.length)"></NoPower>
  </div>
</template>
<script setup name="realestateWarning">
// 获取 permissions 数据
import useUser from '@/store/user'
// 获取所有的菜单
import { realestateWarningTabs } from '@/const/menu'
  
const userInfo = useUser()
// 过滤tab权限
const tabConfigs = computed(() => {
  const { permissions } = userInfo ?? {}
  return (
    realestateWarningTabs.filter((item) => {
      item.label = item.text
      return permissions[item.permissionCode]
    }) ?? []
  )
})
</script>

本质就是使用 一个 tabConfigs 来筛选需要显示哪些 tab,其中操作是从全局 store 中获取当前用户的权限码列表,然后判断其中是否存在当前需要的权限码,如果有对应的权限码,就加进来。

2. 组件方式

我们可以单独写一个组件,在组件内部进行权限的控制操作,主要是通过插槽的形式把内部需要展示的组件引入进来,在需要加权限的地方进行组件的引入,组件内部的逻辑和函数方式基本无异。这样就可以统一管理权限了,使用起来也比较方便。代码如下:

<template>
  <div>
    <Permission :value="AAAAAA">
      <AAAAAA/>
    </Permission>
    <Permission :value="BBBBBB">
      <BBBBBB/>
    </Permission>
    <Permission :value="CCCCCC">
      <CCCCCC/>
    </Permission>
  </div>
</template>
<script>
  import { Permission } from './Permission';
</script>

<script>
// 获取 permissions 数据
import useUser from '@/store/user'
// 获取所有的菜单
import { realestateWarningTabs } from '@/const/menu'

export default defineComponent({
  props: {
    value: {
      type: [Number, Array, String],
      default: '',
    },
  },
  setup(props, { slots }) {
		const userInfo = useUser()
  	const { permissions } = userInfo ?? {}
    const { hasPermission } = usePermission();

    function renderAuth() {
      const { value } = props;
      if (!value) {
        return getSlot(slots);
      }
      return permissions[value] ? getSlot(slots) : null;
    }

    return () => {
      return renderAuth();
    };
  },
});
</script>

3. 指令方式

指令方式就是自己写个指令,在需要的组件上使用指令就行了。如下:

引用:

<template>
  <div>
    <AAAAAA v-permission="AAAAAA"/>
    <BBBBBB v-permission="BBBBBB"/>
    <CCCCCC v-permission="CCCCCC"/>
  </div>
</template>

编写指令:

import { createApp, reactive, watchEffect } from "vue"
const codeList = reactive([1, 2, 3])

const hasPermission = (value) => {
    return codeList.includes(value)
}

app.directive("permission", {
    updated(el, binding) {
        let update = () => {
            let valueNotChange = binding.value === binding.oldValue
            let oldHasPermission = hasPermission(binding.oldValue)
            let newHasPermission = hasPermission(binding.value)
            let permissionNotChange = oldHasPermission === newHasPermission
            if (valueNotChange && permissionNotChange) return
            if (newHasPermission) {
                addEl(el)
            } else {
                removeEl(el)
            }
        };
        if (el._watchEffect) {
            update()
        } else {
            el._watchEffect = watchEffect(() => {
                update()
            })
        }
    },
})

在绑定元素挂载后调用,使用 permissions 判断当前用户是否存在通过指令插入的按钮需要的权限码,如果不存在,直接移除绑定的元素。

在实际的开发中也会有其他的控制方式,在各种论坛中也看到了,使用装饰器来做的,其实不管怎么做,都是为了抽离业务逻辑,是我们用起来跟简单为目的。

相关推荐
耶啵奶膘26 分钟前
uniapp-是否删除
linux·前端·uni-app
魔道不误砍柴功1 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2341 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨1 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
王哈哈^_^2 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie2 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
开心工作室_kaic3 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿3 小时前
webWorker基本用法
前端·javascript·vue.js
P.H. Infinity3 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq