当前位置: 首页 > news >正文

【vue】vue中按钮权限控制:

文章目录

        • 一、获取权限码
        • 二、三种按钮级别的权限控制方式
            • 【1】函数方式
            • 【2】组件方式
            • 【3】指令方式


一、获取权限码

要做权限控制,肯定需要一个code,无论是权限码还是角色码都可以,一般后端会一次性返回,然后全局存储起来就可以了,在登录成功以后获取并保存到全局的store中:

import { defineStore } from 'pinia';
export const usePermissionStore = defineStore({state: () => ({// 权限代码列表permCodeList: [],}),getters: {// 获取getPermCodeList(){return this.permCodeList;}, },actions: {// 存储setPermCodeList(codeList) {this.permCodeList = codeList;},// 请求权限码async changePermissionCode() {const codeList = await getPermCode();this.setPermCodeList(codeList);}}
})

二、三种按钮级别的权限控制方式

【1】函数方式

使用示例如下:

<template><a-button v-if="hasPermission(['20000', '2000010'])" color="error" class="mx-4">拥有[20000,2000010]code可见</a-button>
</template><script lang="ts">import { usePermission } from '/@/hooks/web/usePermission';export default defineComponent({setup() {const { hasPermission } = usePermission();return { hasPermission };},});
</script>

本质上就是通过v-if,只不过是通过一个统一的权限判断方法hasPermission:

export function usePermission() {function hasPermission(value, def = true) {// 默认视为有权限if (!value) {return def;}const allCodeList = permissionStore.getPermCodeList;if (!isArray(value)) {return allCodeList.includes(value);}// intersection是lodash提供的一个方法,用于返回一个所有给定数组都存在的元素组成的数组return (intersection(value, allCodeList)).length > 0;return true;}
}

很简单,从全局store中获取当前用户的权限码列表,然后判断其中是否存在当前按钮需要的权限码,如果有多个权限码,只要满足其中一个就可以。

【2】组件方式

除了通过函数方式使用,也可以使用组件方式,Vue vben admin提供了一个Authority组件,使用示例如下:

<template><div><Authority :value="RoleEnum.ADMIN"><a-button type="primary" block> 只有admin角色可见 </a-button></Authority></div>
</template>
<script>import { Authority } from '/@/components/Authority';import { defineComponent } from 'vue';export default defineComponent({components: { Authority },});
</script>

使用Authority包裹需要权限控制的按钮即可,该按钮需要的权限码通过value属性传入,接下来看看Authority组件的实现。

<script lang="ts">import { defineComponent } from 'vue';import { usePermission } from '/@/hooks/web/usePermission';import { getSlot } from '/@/utils/helper/tsxHelper';export default defineComponent({name: 'Authority',props: {value: {type: [Number, Array, String],default: '',},},setup(props, { slots }) {const { hasPermission } = usePermission();function renderAuth() {const { value } = props;if (!value) {return getSlot(slots);}return hasPermission(value) ? getSlot(slots) : null;}return () => {return renderAuth();};},});
</script>

同样还是使用hasPermission方法,如果当前用户存在按钮需要的权限码时就原封不动渲染Authority包裹的内容,否则就啥也不渲染。

【3】指令方式

使用示例如下:

<a-button v-auth="'1000'" type="primary" class="mx-4"> 拥有code ['1000']权限可见 </a-button>

实现如下:

import { usePermission } from '/@/hooks/web/usePermission';function isAuth(el, binding) {const { hasPermission } = usePermission();const value = binding.value;if (!value) return;if (!hasPermission(value)) {el.parentNode?.removeChild(el);}
}const mounted = (el, binding) => {isAuth(el, binding);
};const authDirective = {// 在绑定元素的父组件// 及他自己的所有子节点都挂载完成后调用mounted,
};

// 注册全局指令

export function setupPermissionDirective(app) {app.directive('auth', authDirective);
}

只定义了一个mounted钩子,也就是在绑定元素挂载后调用,依旧是使用hasPermission方法,判断当前用户是否存在通过指令插入的按钮需要的权限码,如果不存在,直接移除绑定的元素。

很明显,权限控制的实现有两个问题,一是不能动态更改按钮的权限,二是动态更改当前用户的权限也不会生效。
【1】解决第一个问题很简单,因为上述只有删除元素的逻辑,没有加回来的逻辑,那么增加一个updated钩子:

app.directive("auth", {mounted: (el, binding) => {const value = binding.valueif (!value) returnif (!hasPermission(value)) {// 挂载的时候没有权限把元素删除removeEl(el)}},updated(el, binding) {// 按钮权限码没有变化,不做处理if (binding.value === binding.oldValue) return// 判断用户本次和上次权限状态是否一样,一样也不用做处理let oldHasPermission = hasPermission(binding.oldValue)let newHasPermission = hasPermission(binding.value)if (oldHasPermission === newHasPermission) return// 如果变成有权限,那么把元素添加回来if (newHasPermission) {addEl(el)} else {// 如果变成没有权限,则把元素删除removeEl(el)}},
})const hasPermission = (value) => {return [1, 2, 3].includes(value)
}const removeEl = (el) => {// 在绑定元素上存储父级元素el._parentNode = el.parentNode// 在绑定元素上存储一个注释节点el._placeholderNode = document.createComment("auth")// 使用注释节点来占位el.parentNode?.replaceChild(el._placeholderNode, el)
}const addEl = (el) => {// 替换掉给自己占位的注释节点el._parentNode?.replaceChild(el, el._placeholderNode)
}

主要就是要把父节点保存起来,不然想再添加回去的时候获取不到原来的父节点,另外删除的时候创建一个注释节点给自己占位,这样下次想要回去能知道自己原来在哪。

【2】第二个问题的原因是修改了用户权限数据,但是不会触发按钮的重新渲染,那么我们就需要想办法能让它触发,这个可以使用watchEffect方法,我们可以在updated钩子里通过这个方法将用户权限数据和按钮的更新方法关联起来,这样当用户权限数据改变了,可以自动触发按钮的重新渲染:

import { createApp, reactive, watchEffect } from "vue"
const codeList = reactive([1, 2, 3])const hasPermission = (value) => {return codeList.includes(value)
}app.directive("auth", {updated(el, binding) {let update = () => {let valueNotChange = binding.value === binding.oldValuelet oldHasPermission = hasPermission(binding.oldValue)let newHasPermission = hasPermission(binding.value)let permissionNotChange = oldHasPermission === newHasPermissionif (valueNotChange && permissionNotChange) returnif (newHasPermission) {addEl(el)} else {removeEl(el)}};if (el._watchEffect) {update()} else {el._watchEffect = watchEffect(() => {update()})}},
})

将updated钩子里更新的逻辑提取成一个update方法,然后第一次更新在watchEffect中执行,这样用户权限的响应式数据就可以和update方法关联起来,后续用户权限数据改变了,可以自动触发update方法的重新运行。

相关文章:

【vue】vue中按钮权限控制:

文章目录 一、获取权限码二、三种按钮级别的权限控制方式【1】函数方式【2】组件方式【3】指令方式 一、获取权限码 要做权限控制&#xff0c;肯定需要一个code&#xff0c;无论是权限码还是角色码都可以&#xff0c;一般后端会一次性返回&#xff0c;然后全局存储起来就可以了…...

【博客695】k8s subPathExpr作用

k8s subPathExpr作用 场景&#xff1a; 对于一个deployment或者job拉起的服务&#xff0c;所有pod都是一样的配置&#xff0c;如果都挂载了宿主机的同一个目录&#xff0c;那么就会互相干扰&#xff0c;我们希望挂载相同目录&#xff0c;且在这个目录下&#xff0c;每个pod建立…...

微信小程序中键盘弹起输入框自动跳到键盘上方处理

效果展示 键盘未弹起时 键盘弹起后&#xff1a; 实现方式 话就不多说了 我直接贴代码了 原理就是用你点击的输入框的底部 距离顶部的位置 减去屏幕高度除以2&#xff0c;然后设成负值&#xff0c;再将这个值给到最外层相对定位的盒子的top属性&#xff0c;这样就不会出现顶…...

excel将主信息和明细信息整理为多对多(每隔几行空白如何填充)

excel导出的数据是主信息和明细信息形式。 方法如下:1、首先&#xff0c;从第一个单元格开始选中要填充的数据区域。2、按CtrlG或者F5调出定位对话框&#xff0c;点击左下角的【定位条件】。3、在【定位条件】中选择【空值】&#xff0c;然后点击【确定】按钮。4、按照上述操作…...

卷积神经网络实现彩色图像分类 - P2

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营-第P2周&#xff1a;彩色识别&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子…...

【博客694】k8s kubelet 状态更新机制

k8s kubelet 状态更新机制 场景&#xff1a; 当 Kubernetes 中 Node 节点出现状态异常的情况下&#xff0c;节点上的 Pod 会被重新调度到其他节点上去&#xff0c;但是有的时候我们会发现节点 Down 掉以后&#xff0c;Pod 并不会立即触发重新调度&#xff0c;这实际上就是和 K…...

【博客692】grafana如何解决step动态变化时可能出现range duration小于step

grafana如何解决step动态变化时可能出现range duration小于step 1、grafana中的step和resolution grafana中的 “step” grafana本身是没有提供step参数的&#xff0c;因为仪表盘根据查询数据区间以及仪表盘线条宽度等&#xff0c;对于不同查询&#xff0c;相同的step并不能…...

eNSP:ibgp的破水平切割练习

实验要求&#xff1a; 拓扑展示&#xff1a; 命令操作&#xff1a; R1&#xff1a; <Huawei>sys [Huawei]sys r1 [r1]int g 0/0/1 [r1-GigabitEthernet0/0/1]ip add 12.1.1.1 24 [r1-GigabitEthernet0/0/1]int lo0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]osp…...

maven是什么?安装+配置

目录 1.什么是maven&#xff1f; 1.2.maven的核心功能是什么&#xff1f; 2.Maven安装配置 2.1Maven的安装 2.2Maven环境配置 1.配置 MAVEN_HOME &#xff0c;变量值就是你的 maven 安装的路径&#xff08;bin 目录之前一级目录&#xff09; 2.将MAVEN_HOME 添加到Path系…...

基于长短期神经网络LSTM的多分类代码

目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 基于长短期神经网络LSTM的股票预测 MATALB编程实现,附有代码:基于长短期神经网络LSTM的多分类代码,基于LSTM的多分类预测-深度学习文档类资源-CSDN文库 https://download.csdn.net/download/abc991835105/88184779 效果图 结果…...

利用爬虫爬取图片并保存

1 问题 在工作中&#xff0c;有时会遇到需要相当多的图片资源&#xff0c;可是如何才能在短时间内获得大量的图片资源呢&#xff1f; 2 方法 我们知道&#xff0c;网页中每一张图片都是一个连接&#xff0c;所以我们提出利用爬虫爬取网页图片并下载保存下来。 首先通过网络搜索…...

设计模式之Bridge模式的C++实现

目录 1、Bridge模式的提出 2、Bridge模式的定义 3、Bridge模式总结 4、需求描述 5、多继承方式实现 6、使用Bridge设计模式实现 1、Bridge模式的提出 在软件功能模块设计中&#xff0c;如果类的实现功能划分不清晰&#xff0c;使得继承得到的子类往往是随着需求的变化&am…...

springboot异步任务

在Service类声明一个注解Async作为异步方法的标识 package com.qf.sping09test.service;import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;Service public class AsyncService {//告诉spring这是一个异步的方法Asyncp…...

Flutter父宽度自适应子控件的宽度

需求&#xff1a; 控件随着金币进行自适应宽度 image.png 步骤&#xff1a; 1、Container不设置宽度&#xff0c;需要设置约束padding&#xff1b; 2、文本使用Flexible形式&#xff1b; Container(height: 24.dp,padding: EdgeInsetsDirectional.only(start: 8.dp, end: 5.d…...

什么是 API 安全?学习如何防止攻击和保护数据

随着 API 技术的普及&#xff0c;API 安全成为了一个越来越重要的问题。本文将介绍什么是 API 安全&#xff0c;以及目前 API 面临的安全问题和相应的解决方案。 什么是 API 安全 API 安全是指保护 API 免受恶意攻击和滥用的安全措施。API 安全通常包括以下几个方面&#xff1…...

简述 TCP 和 UDP 的区别以及优缺点和使用场景?

一、TCP与UDP区别总结&#xff1a; 1、TCP面向连接&#xff08;如打电话要先拨号建立连接&#xff09;;UDP是无连接的&#xff0c;即发送数据之前不需要建立连接 2、TCP提供可靠的服务。也就是说&#xff0c;通过TCP连接传送的数据&#xff0c;无差错&#xff0c;不丢失&…...

react进阶

react-virtualized的高阶组件&#xff0c;Autosize可以使屏幕适配。使用render-props模式来获取到AutoSizer组件暴露的width和height属性。JSON.parse(JSON.stringify())不适用于有undefined的数据。 深拷贝的使用&#xff0c;不能使用在有undefined的数据中。有直接过滤undefi…...

使用windows搭建WebDAV服务,并内网穿透公网访问【无公网IP】

文章目录 1. 安装IIS必要WebDav组件2. 客户端测试3. 使用cpolar内网穿透&#xff0c;将WebDav服务暴露在公网3.1 打开Web-UI管理界面3.2 创建隧道3.3 查看在线隧道列表3.4 浏览器访问测试 4. 安装Raidrive客户端4.1 连接WebDav服务器4.2 连接成功4.2 连接成功 1. Linux(centos8…...

科技感响应式管理系统后台登录页ui设计html模板

做了一个科技感的后台管理系统登录页设计&#xff0c;并且尝试用响应式布局把前端html写了出来&#xff0c;发现并没有现象中的那么容易&#xff0c;chrome等标准浏览器都显示的挺好&#xff0c;但IE11下面却出现了很多错位&#xff0c;兼容起来还是挺费劲的&#xff0c;真心不…...

Lombok的使用及注解含义

文章目录 一、简介二、如何使用2.1、在IDEA中安装Lombok插件2.2、添加maven依赖 三、常用注解3.1、Getter / Setter3.2、ToString3.3、NoArgsConstructor / AllArgsConstructor3.4、EqualsAndHashCode3.5、Data3.6、Value3.7、Accessors3.7.1、Accessors(chain true)3.7.2、Ac…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

DiscuzX3.5发帖json api

参考文章&#xff1a;PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下&#xff0c;适配我自己的需求 有一个站点存在多个采集站&#xff0c;我想通过主站拿标题&#xff0c;采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...