页面元素权限控制
按钮权限控制
按钮权限控制的交互方式无非两种:"不可见" 和 "可见不可点"。
不可见
不可见的交互方式相对简单,控制DOM
的显示隐藏即可。
【页面元素权限控制】在Vue
中可以通过下述方式实现:
v-if
控制其是否显示v-show
控制其是否显示,但不够保险,毕竟v-show
只是把样式改成display: none
,在真实的 DOM 渲染还是存在
React
中可以通过下述方式实现:JSX
中条件判断
const Demo = () => {
return
{boolean && }}
- 使用高阶组件
HOC
,抽离判断逻辑
const Demo = () => {
return code...
}/** 高阶组件 */
const HOC = (Com: Com: React.ComponentType) => {
if (whiteList.includes(code)) return
return null;
}
可见不可点
页面中有很多功能点,如果有些功能点用户不能操作而不显示
DOM
,可能会导致页面布局错乱,或者影响页面的美观,有些产品在控制功能点权限时期望元素“可见不可点”。在
Vue
中可以通过下述方式实现:- 自定义指令
Vue.directive
。使用addEventListener
给元素增加一个捕获事件,捕获事件会优先于@click
触发,然后在捕获事件方法体中使用stopImmediatePropagation
阻止事件冒泡和其它相同事件的触发,因此达到控制元素不可点击的目的
如果多个事件监听器被附加到相同元素的相同事件类型上,当此事件触发时,它们会按其被添加的顺序被调用。如果在其中一个事件监听器中执行
stopImmediatePropagation()
,那么剩下的事件监听器都不会被调用。
MSDN - stopImmediatePropagation
// 注册自定义指令脚本
/** 权限拦截 */
const interception = (event) => {
event && event.stopImmediatePropagation();
}/** 白名单 */
const whiteList = [];
/** 注册指令 */
Vue.directive('permission', {
bind(el, binding) {
/** 不在白名单中 */
if (!whiteList.includes(binding.value)) {
el.style.pointerEvents = 'none';
el.setAttribute('disabled', 'disabled');
el.addEventListener('click', interception, true);
}
},
unbind(el) {
el.removeEventListener('click', interception);
}
});
这里使用
pointer-events
只是一个辅助功能,并不一定意味着元素上的事件监听器永远不会触发,如果后代元素有指定 pointer-events
并允许成为事件目标的话,是可以触发父元素事件,而且单纯依靠 CSS
属性来控制不点击,还是有风险,因此这里仅作辅助作用。在CSS3
的pointer-events
属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件的target
。 更多用法参考: MSDN - pointer-events
React
中可以通过下述方式实现:import { Button } from 'antd';
import axios from 'axios';
import React, { Component } from 'react';
/** 按钮权限控制高阶组件 */
const RbacHOC = (Com: any) => {
return class WrappedComponent extends Component {
divRef = React.createRef();
componentDidMount() {
this.fetchWilteList();
}componentWillUnmount() {
this.divRef.current?.removeEventListener('click', this.intercept);
}/** 获取黑白名单 */
fetchWilteList = async () => {
try {
const { code, data } = await axios.get(`${url}`).then((res: any) => res.data);
if (code === 200 && !data) {
this.register();
}
} catch (error) {
this.register();
}
};
/** 注册捕获事件,拦截事件 */
register = () => {
this.divRef.current?.addEventListener('click', this.intercept, true);
};
/** 拦截函数 */
intercept = (event: Event) => {
event.stopImmediatePropagation();
message.info('你没有权限使用该功能!!!');
};
render() {
const { props } = this;
return ( );
}
};
};
export default RbacHOC;
页面组件中使用:
import React from 'react';
const Demo = () => {
return <>coding...>
}export default RbacHOC(inject('store')(observer(Demo)));
// export default inject('store')(observer(RbacHOC(Demo));
// 不能这么写,因为store改变后WrappedComponent组件不会重新渲染,继而传给Demo组件的props不变,Demo也不会重新渲染
如果不想每次点击触发时都去调用接口拿黑白名单,可以将存放黑白名单数据的
store
传到高阶组件中import React from 'react';
const Demo = () => {
return <>coding...>
}export default inject('xxxstore')(RbacHOC(inject('store')(observer(Demo))));
参考 基于 Element 按钮权限实现方案
推荐阅读
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 分享!如何分分钟实现微信扫二维码调用外部浏览器打开指定页面的功能
- mysql中视图事务索引与权限管理
- iOS|iOS runtime应用整理
- 你也许不知道的Vuejs|你也许不知道的Vuejs - 花式渲染目标元素
- React.js的表单(六)
- 8、Flask构建弹幕微电影网站-搭建后台页面-密码修改、主页控制面板
- 最新Mac系统安装fastlane|最新Mac系统安装fastlane /usr/bin 权限问题
- 小程序开发|小程序开发 - 页面传值url类型
- 集合框架(集合嵌套存储和遍历元素的案例代码实现)