Vue3自定义指令封装-按钮权限控制v-permission、hasPermissions

        背景:平常所接触到的系统权限控制,大部分都是菜单、路由级别的控制,但后台管理系统中,很多操作都是与职责和角色挂钩的,同样一个列表,不同人的操作列并不都一样,有些页面存在一些含有重要数据的组件,也会进行相应的权限控制,仅让领导层能看到。

        按钮级权限:根据用户的权限不同,对不同的按钮进行权限控制,对同一组数据,不同的用户是否可以增删改查。对某些用户来说是只读浏览数据,对某些用户来说是可编辑的数据。除了按钮,比如页面中的某个字段,某个div,某个组件要求根据当前用户的权限进行控制时,都可以称为按钮级权限。

     因此,有必要实现按钮/组件级别的权限控制,为了更加方便高效地使用更细粒度的权限控制,封装了一个自定义指令插件v-permission,可实现随时注入使用。

v-permission插件

        一个基于Vue3进行封装的自定义指令,在这个插件中,你可以检查传入的系统权限列表和用户拥有的权限列表,来确定用户是否具有某个组件/按钮级别的权限,实现更细粒度的权限控制。

功能:

① 指令:有权限时显示 UI,无权限时不渲染。避免出现用户看得见按钮,点击却无反应或出现无权限提示,这种不友好的使用体验。

②方法:可用于一些前置处理,比如进入页面时,根据是否有权限来判断默认渲染哪个组件作为该用户能看到的首页。

方式一:封装成可下载的npm包

        在公司中,为了减少重复劳动,防止重复造轮子,开发的这种通用插件是直接传到npm上,再下载到项目中使用的,于是笔者将该插件单独写在一个很简单的小项目中,具体可见:

         该插件的源代码及其使用文档均放在该仓库中。

GitHub - yoguoer/v-permissionContribute to yoguoer/v-permission development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/yoguoer/v-permission.git

方式二:在项目中直接封装插件

        当然啦,我们也可以直接在项目中去实现这个插件,下面介绍一下操作步骤。

        1. 在根目录下新建一个directive文件夹,用来存放我们自己开发的所有插件。为了便于区分,我们再建一个vPermission文件夹,用来存放我们的v-permission插件。

        2. 在directive/vPermission/permission.ts文件写入以下内容:

/**
* 权限指令
* 使用: v-permission="{module:'模块名称',auth:'权限key值'}"
* const hasPermi = hasPermissions({ module: 'someModule', auth: 'someAuth' });
*//**  * 初始化全局权限判断方法  * permissionList 系统预先配置的权限列表,包含所有权限信息* permissions 用户当前权限列表(服务端返回接口权限列表数据) */
export function initHasPermission(options: {permissionList: Array<string> | null,permissions: Array<string> | null
}
) {const { permissionList = null, permissions = null } = options;// 返回一个函数,该函数接收一个权限对象并返回是否有权限    return (permission: {module: string,auth: string,}) => {if (!permissionList || !permissions) {throw new Error('permissionList or permissions is null');}if (permission.module && permission.auth) {const value = permissionList[permission.module][permission.auth];return permissions.includes(value);}return false;};
}// 检查权限并执行相应的操作  
function checkPermission(el: any, binding: any, hasPermissions: Function) {if (typeof binding.value === 'object' && binding.value.module && binding.value.auth) {if (!hasPermissions(binding.value)) {el.style.display = 'none';} else {el.style.display = ''; // 如果有权限,确保元素可见  }}
}// 权限指令  
// 创建一个返回指令对象的函数,该函数接受 hasPermissions 函数作为参数  
export default function createPermissionDirective(hasPermissions: Function) {return {mounted(el: any, binding: any) {checkPermission(el, binding, hasPermissions);},updated(el: any, binding: any) {checkPermission(el, binding, hasPermissions);}};
}

        3. 在directive/vPermission/index.ts文件写入以下内容:

import createPermissionDirective from './permission';
import { initHasPermission } from './permission'// Vue 3 插件定义   
const install = function (app: any, options: {permissionList: Array<string> | null,permissions: Array<string> | null
} = {/** permissionList 系统预先配置的权限列表,包含所有权限信息*   permissions 用户当前权限列表(服务端返回接口权限列表数据) */permissionList: null,permissions: null}) {// 初始化权限检查函数 const hasPermissions = initHasPermission(options);// 添加全局方法 $hasPermissions  app.config.globalProperties.$hasPermissions = hasPermissions;// 提供全局的权限检查对象 app.provide('hasPermissions', app.config.globalProperties.$hasPermissions);// 使用 hasPermissions 函数创建指令对象  const permissionDirective = createPermissionDirective(hasPermissions);// 注册全局指令 v-permission  app.directive('permission', permissionDirective);}// 导出插件对象  
export default {install
};

插件使用方法

  • 在你的项目根目录中新建一个permission文件夹,并在文件夹下新建一个index.ts文件和一个modules文件夹。

modules文件夹用来放置不同模块的权限控制文件(一般各个模块各自建一个.ts文件),而index.ts用来遍历读取modules下的所有文件,并将所有文件转换为键值对的形式,整合成一个包含系统所有权限信息的对象,即:{ 模块名:{ 该模块的权限列表 }, ... }。

  • 在index.ts文件中键入以下代码:
/*** 权限配置模块文件,统一引入所有权限配置文件*/
const files = import.meta.glob('./modules/*.ts');
const modules = {};
for (const path in files) {files[path]().then((mod) => {let fileNameMatch = path.match(/([^\/\\]+?)\.\w+$/);let fileName = fileNameMatch ? fileNameMatch[1] : null;modules[fileName as string] = mod?.default});
}export default modules
  • 在modules下新建所需要的模块文件,文件中的内容格式形如以下例子(权限key值: 权限标识):
export default {add: '/add-add',delete: '/delete-delete', edit: '/edit-edit', 
}
  • 引入index.ts中整理好的系统预先配置的权限列表,作为我们所需要的参数permissionList,。
import permissionList from './permission'
  • 通过接口获取当前用户的权限列表,作为我们所需要的参数permissions。
import permissions from '存放服务端返回接口权限列表数据的地方'

permissionList形如:

{"admin": {"add": "/admin-add","delete": "/admin-delete","edit": "/admin-edit"},"user": {"add": "/user-add","delete": "/user-delete"}
}

permissions形如:

["/user-add","/user-delete"
]
  • 在项目中的入口文件中引入 v-permission,将前面提到的两个参数作为选项,然后使用插件并传入选项:
import { createApp } from 'vue'
import App from './views/App.vue'
import permission from "@/directive/permission" 
import permissionList from '@/permission'
import permissions from '存放服务端返回接口权限列表数据的地方'const app = createApp(App);const options = {permissionList,permissions
}app.use(permission, options)app.mount('#app')
  • 在文件中使用。
  • 以指令的方式使用:

    • v-permission指令形式:

      <el-button v-permission="{ module: '模块名', auth: '权限key值' }"> 有权限则显示 </el-button>
      
    • v-if指令形式:

      <el-button v-if="hasPermissions({ module: '模块名', auth: '权限key值' })"> 有权限则显示 </el-button>
      
  • 以方法的方式使用:

    import { inject } from "vue";// 注入权限判断方法 hasPermissions
    const hasPermissions = inject("hasPermissions");
    if (hasPermissions({ module: '模块名', auth: '权限key值' })) {console.log("用户有权限");
    } else {console.log("用户没有权限");
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/9504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

B+树(B+ Tree)

B树&#xff08;B Tree&#xff09;是一种对B树&#xff08;B-Tree&#xff09;的改进版本&#xff0c;它在数据库系统和文件系统中作为索引结构得到了广泛的应用&#xff0c;特别是在磁盘存储的场景下。B树保留了B树的基本特征&#xff0c;如自平衡、多路分支等&#xff0c;但…

excel中怎么跳转到指定的单元格?

也许你会有这样的需求&#xff0c;如A1单元格中显示B100这种单元格地址&#xff0c;怎么做以点一下就跳转到B100&#xff1f; 一、设置公式 B1HYPERLINK("#"&MID(CELL("FILENAME",A1),FIND("]",CELL("FILENAME",A1))1,99)&&…

java-函数式编程-jdk

背景 函数式接口很简单&#xff0c;但是不是每一个函数式接口都需要我们自己来写jdk 根据 有无参数&#xff0c;有无返回值&#xff0c;参数的个数和类型&#xff0c;返回值的类型 提前定义了一些通用的函数式接口 IntPredicate 参数&#xff1a;有一个&#xff0c;类型是int类…

VSCode(安装)

前言 VSCode&#xff08;全称&#xff1a;Visual Studio Code&#xff09;是一款由微软开发且跨平台的免费源代码编辑器。该软件支持语法高亮、代码自动补全&#xff08;又称 IntelliSense&#xff09;、代码重构、查看定义功能&#xff0c;并且内置了命令行工具和 Git …

Redis面试高频问题

什么是缓存穿透 ? 怎么解决 ? 缓存穿透是指查询一个一定不存在的数据&#xff0c;如果从存储层查不到数据则不写入缓存&#xff0c;这将导致这个不存在的数据每次请求都要到数据库去查询&#xff0c;可能导致数据库挂掉。这种情况大概率是遭到了攻击。解决方案的话&#xff0…

C++ 实现一个不能被copy的类

文章目录 实现一个不能被copy的类1.先实现父类2.代码实现 小结 实现一个不能被copy的类 1.先实现父类 一个类不能被copy&#xff0c;首先肯定是构造函数没有。其次&#xff0c;拷贝构造不能有赋值构造函数也不能有 基于这三点&#xff0c;就容易实现了。下边看看代码。 2.代…

spring开发问题总结(持续更新)

开始 最近在做项目的时候&#xff0c;总遇到一些大小不一&#xff0c;奇形怪状的问题。 现在终于有时间来总结一下遇到的问题&#xff0c;以备复习之用。 以下提到的问题经过简化&#xff0c;不代表任何项目代码或问题。 问题1&#xff1a;未完成任务状态搜索结果有误&#x…

【贪心算法】Leetcode 134. 加油站【中等】

加油站 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发&#xff0c;开始时油箱为空。 给定两个整数数组 gas 和…

【Android】自定义View不显示的一种问题

需求 在自定义View里面添加一种颜色表示某个数据到达了某个状态 问题 颜色没有显示 问题分析 在代码中定义一种颜色和画笔 private int wathetBlue;private Paint backgroundWathetBlue;在init方法里面初始化 wathetBlue Color.argb(205, 165, 209, 254);backgroundWat…

5月游戏市场迎来新的体验,网易两款游戏重磅出炉

易采游戏网5月9日消息&#xff0c;随着科技的飞速发展&#xff0c;手机游戏已经成为人们休闲娱乐的重要方式。在这个领域&#xff0c;网易作为国内领先的游戏开发商&#xff0c;一直致力于为玩家带来高品质的游戏体验。近日&#xff0c;网易携手国际大厂Square Enix&#xff0c…

2024年数维杯高校数学建模竞赛(B题) 建模解析| 生物质和煤共热解问题的研究 |小鹿学长带队指引全代码文章与思路

我是鹿鹿学长&#xff0c;就读于上海交通大学&#xff0c;截至目前已经帮200人完成了建模与思路的构建的处理了&#xff5e; 本篇文章是鹿鹿学长经过深度思考&#xff0c;独辟蹊径&#xff0c;实现综合建模。独创复杂系统视角&#xff0c;帮助你解决数维杯的难关呀。 完整内容可…

Flink物理分区概念与分类详解

Apache Flink是一个分布式流处理框架&#xff0c;它允许在大规模数据流上进行实时计算。在Flink中&#xff0c;数据如何在不同的任务&#xff08;Task&#xff09;之间传输是一个关键因素&#xff0c;直接影响到系统的性能和可扩展性。物理分区&#xff08;Physical Partitioni…

在线教育系统平台软件,在线教育市场需求怎么样呢?

在线教育发展至今&#xff0c;通过互联网技术&#xff0c;有效地缓解了我国师资不足、优质教育资源供给不均等问题。根据速途研究院公开数据显示&#xff0c;中国在线教育用户规模呈稳定增长趋势&#xff0c;增长率也在逐年提高。我国在线教育市场需求如何? 一、市场预期&…

QML基础语法七

模型视图代理 1. 模型&#xff1a;数据及其结构&#xff0c;多种QML创建模型 2. 视图&#xff1a;显示数据容器&#xff0c;数据可以通过列表或表格的形式显示 3. 委托&#xff1a;控制数据如何在视图中显示&#xff0c;委托获取、封装了模型中每个数据&#xff0c;需要通过委…

创建Spring Boot项目及配置

目录 一、创建项目所需要的插件 1、安装插件 二、创建项目 三、创建项目所面临的常见问题。 1、IDEA不能识别 2、无效的发行版本 3、确认jar包是否下载成功 一、创建项目所需要的插件 1、安装插件 首先需要在IDEA插件里面搜索Spring&#xff0c;选择Spring Boot Helper…

如何去掉溢出内容的overflow属性滚动条

在CSS中&#xff0c;如果你设置了overflow属性为auto或scroll&#xff0c;并且内容确实超出了容器的大小&#xff0c;那么浏览器会自动显示滚动条。但是&#xff0c;如果你想在某些情况下隐藏这些滚动条&#xff0c;有几种方法可以尝试&#xff0c;但请注意&#xff0c;这些方法…

政安晨:【Keras机器学习示例演绎】(四十一)—— 使用预先训练的词嵌入

目录 设置 简介 下载新闻组 20 数据 让我们来看看这些数据 清洗数据并将数据分成训练集和验证集 创建词汇索引 加载预训练的词嵌入 建立模型 训练模型 导出端到端模型 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与…

Python批量修改图片文件名中的指定名称

批量处理图像时&#xff0c;图片名有时需要统一&#xff0c;本教程仅针对图片中名如&#xff1a;0001x4.png&#xff0c;批量将图片名中的x4去除&#xff0c;只留下0001.png的情况。 如果想要按照原图片顺序批量修改图片名&#xff0c;参考其它博文&#xff1a;按照原顺序批量…

Vue中常用指令

Vue中的常用指令 Vue中的常用指令内容渲染指令条件渲染指令事件绑定指令内联语句事件处理函数给事件处理函数传参 属性绑定指令列表渲染指令v-for中的key 双向绑定指令 Vue中的常用指令 概念&#xff1a;指令 是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。Vue 会根据不同的【…