欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

按钮级的权限控制

程序员文章站 2022-07-14 15:32:25
...

1.背景

        近期在开发云服务项目,对于button级别的权限控制有一定的要求,但是一处处改的话比较吃力不讨好,费时费力,就想着做一个封装。

基础环境:vue + element

2.尝试

      1⃣️封装button组件

             第一想法就是封装一个button组件,然后在需要的地方引用,但是这个想法还是有个bug,不管button组件封装的如何,但是总需要把之前的button全部替换为新的button组件,这个虽然省一点时间,但是很不满意。当然,代码还是要贴出来,留个纪念吧。

<template>
  <el-button
    :loading="buttonDct.loading"
    :disabled="disabledStatus"
    :type="buttonDct.type"
    :icon="buttonDct.icon"
    :plain="buttonStyle.plain"
    :round="buttonStyle.round"
    :circle="buttonStyle.circle"
    @click="clickBtn"
  >
    <slot/>
  </el-button>
</template>
<script>
import {currentActionIsDisabled} from "@/helpers/policy.js";
export default {
	props: {
		/**
		 * button属性
		 * type 类型	string	primary / success / warning / danger / info / text, 默认为空
		 * icon	图标类名	string, 默认为空
		 * action 事件名 string, 默认为空
		 * product 产品名 string, 默认为空
		 * loading	是否加载中状态	boolean,默认false
		 * buttonStyle 按钮风格 plain(朴素按钮)/round(圆角按钮)/circle(圆形按钮), 默认为空
		 */
		buttonDct: {
			type: Object,
			default: () => {
				return {
					type: "",
					icon: "",
					action: "",
					product: "",
					loading: false,
					buttonStyle: "",
				};
			},
		},
	},
	data() {
		return {
			// 是否禁用,默认是
			disabledStatus: true,
			// 按钮风格字典
			buttonStyle: {
				"plain": false,
				"round": false,
				"circle": false,
			},
		};
	},
	watch: {
		buttonDct: {
			handler: function() {
				this.loadDisabledStatus();
			},
			immediate: true,
			deep: true,
		},
	},
	methods: {
		// 按钮的点击事件
		clickBtn() {
			this.$emit("click");
		},
		/**
		 * 获取当前button的状态
		 * true:禁用,false:可用
		 */
		async loadDisabledStatus() {
			const {action, product, buttonStyle} = this.buttonDct;
			this.formatButtonStyle(buttonStyle);
			let disabledStatus = true;
			if (action && product) {
                // currentActionIsDisabled为我封装的权限判断方法,在这就不展示了
				disabledStatus = await currentActionIsDisabled(product, action);
			}
			this.disabledStatus = disabledStatus;
		},
		// 格式化button的风格
		formatButtonStyle(bStyle) {
			// 判断当前风格是否存在于button风格字典,如果存在,则设为true,反之,不做任何操作
			if (this.buttonStyle.hasOwnProperty(bStyle)) {
				this.buttonStyle[bStyle] = true;
			}
		},
	},
};
</script>

              2⃣️vue自定义指令--directive

                     第二时间想到了这个黑科技,定一个专属于项目的指令,好像是个不错的选择。

                     对于directive不熟悉的可以看一下官方文档,还是很详细的。传送门

                     思路:根据判断权限的方法返回的结果,为当前button添加class(is-disabled),当然,因为使用的是element,所以button添加的是is-disabled这个class,不过这个还是要根据各自的实际情况修改,不要照本全搬。

                     废话不说,上代码:

import Vue from "vue";
// currentActionIsDisabled为权限判断方法
import {currentActionIsDisabled} from "@/helpers/policy.js";

// 注册一个全局自定义指令 `v-yh-btn-muddy`
Vue.directive("yh-btn-muddy", {
	// 当button无权限时,为button添加class(is-disabled)
	inserted: async function(el, binding) {
		const {action, product} = binding.value;
		const disabled = await currentActionIsDisabled(product, action);
		if (disabled) {
			el.classList.add("is-disabled");
		}
	},
});

就是那么简单,事件的两个参数(el, binding)分别为当前节点和自定义的参数。

现在只需要挂载在全局即可:

在main.js里引入即可

import "./directives/yh-access-muddy";

到现在为止基本完成了,你可以像使用v-modal一样使用v-yh-btn-muddy了。

现在要做的是为每个button增加v-yh-btn-muddy指令,虽然也会费点精力,但相对于刚开始的实现方式,这种方式明显精简了很多。如果你有其他更好的方式,欢迎分享。