更好一点的:Vue 利用指令实现禁止反复发送请求
理论上可以用于任何元素,生效时会在元素上出现一个同大小的灰色蒙层(button元素会该表原生的disabled属性)。
/**
* 当元素触发发起请求后,当发起的请求中最后一个请求的结果返回(不关心返回顺序和结果),解锁元素禁用。
* 优化:用一个pending记录所有请求,逐个判定是否返回结果。
* 指令的方式使用轮询去校验接口是否返回结果,也可以在axios拦截器中,改变store中的数据,
* 然后在页面的computed中处理,不过页面内代码不如一个指令来的方便。
* 也可以用Bus来代替轮询
*/
const forbiddenInterval = 200; /**
* 配合ElementUI逐次查找父节点,目前仅考虑 body 和 dialogue 2个场景
* 将目标节点设为root,将mask(非button元素,el-button实际上就是个原生button元素,直接用原生属性disabled即可)挂在root下
* 并且相对root定位
*/
function findRootTag(el) {
let parent = el.parentNode;
let type = null;
let root = null;
while (parent) {
if (parent.tagName === 'BODY') {
type = 'body';
root = parent;
break;
} else if (parent.getAttribute('role') === 'dialog') {
type = 'dialog';
root = parent;
break;
}
parent = parent.parentNode;
}
return { type, root };
} export default {
inserted(el) {
el.timer = null;
if (el.tagName === 'BUTTON') {
el.forbiddenClick = () => {
el.disabled = true;
el.classList.add('is-disabled');
el.timer = setInterval(() => {
if (window.currentResq.done) {
clearInterval(el.timer);
el.disabled = false;
el.classList.remove('is-disabled');
}
}, forbiddenInterval);
};
el.addEventListener('click', el.forbiddenClick);
} else {
const { type, root} = findRootTag(el);
let mask = document.createElement('div');
if (type === 'dialog') {
/* dialog上的mask z-index 设置的较大 */
mask.setAttribute('style',
`
position: absolute;
diplay: none;
background-color: #e4e7ed;
cursor: not-allowed;
opacity: .4;
z-index: 9999;
`
);
} else {
mask.setAttribute('style',
`
position: absolute;
diplay: none;
background-color: #e4e7ed;
cursor: not-allowed;
opacity: .4;
z-index: 1000;
`
);
} mask.classList.add('mask');
root.appendChild(mask);
el.instance = mask;
el.root = root;
el.type = type;
}
},
update(el, binding) {
if (el.tagName !== 'BUTTON' && binding.value !== binding.oldValue) {
const root = el.root;
const type = el.type;
const scrollTop = root.scrollTop || document.documentElement.scrollTop;
const scrollLeft = root.scrollLeft || document.documentElement.scrollLeft;
const mask = el.instance;
const elRect = el.getBoundingClientRect();
mask.style.width = `${elRect.width}px`;
mask.style.height = `${elRect.height}px`;
if (type === 'body') {
mask.style.top = `${elRect.top + scrollTop}px`;
mask.style.left = `${elRect.left + scrollLeft}px`;
} else if (type === 'dialog') {
const rootRect = root.getBoundingClientRect();
mask.style.top = `${elRect.top - rootRect.top}px`;
mask.style.left = `${elRect.left - rootRect.left}px`;
}
mask.style.display = 'block'; el.timer = setInterval(() => {
if (window.currentResq.done) {
clearInterval(el.timer);
mask.style.display = 'none';
}
}, forbiddenInterval);
}
},
unbind(el) {
if (el.instance) {
el.root.removeChild(el.instance);
}
if (el.forbiddenClick) {
document.removeEventListener('click', el.forbiddenClick);
}
},
};
还有很多可以改进的地方,比如应该是有办法去兼容dialog这种会禁用body滚动并且本身也会有动条的元素,等下一个项目去实践一下脑子里的想法。
更好一点的:Vue 利用指令实现禁止反复发送请求的更多相关文章
- Vue 利用指令实现禁止反复发送请求
前端做后台管控系统,在某些接口请求时间过长的场景下,需要防止用户反复发起请求. 假设某场景下用户点击查询按钮后,后端响应需要长时间才能返回数据.那么要规避用户返回点击查询按钮无外乎是让用户无法在合理时 ...
- Vue项目中使用Vuex + axios发送请求
本文是受多篇类似博文的影响写成的,内容也大致相同.无意抄袭,只是为了总结出一份自己的经验. 一直以来,在使用Vue进行开发时,每当涉及到前后端交互都是在每个函数中单独的写代码,这样一来加大了工作量,二 ...
- vue自定义指令,比onerror更优雅的方式实现当图片加载失败时使用默认图,提供三种方法
首先,来看下效果图(演示一下图片正常加载与加载失败时的效果) 在线体验地址:https://hxkj.vip/demo/vueImgOnerror/ 一.常规方法解决 我们都知道,img标签支持one ...
- vue之指令
一.什么是VUE? 它是构建用户界面的JavaScript框架(让它自动生成js,css,html等) 二.怎么使用VUE? 1.引入vue.js 2.展示HTML <div id=" ...
- vue自定义指令clickoutside使用以及扩展用法
vue自定义指令clickoutside使用以及扩展用法 产品使用vue+element作为前端框架.在功能开发过程中,难免遇到使用element的组件没办法满足特殊的业务需要,需要对其进行定制,例如 ...
- vue自定义指令clickoutside扩展--多个元素的并集作为inside
都是个人理解,如果发现错误,恳请大家批评指正,谢谢.还有我说的会比较啰嗦,因为是以自身菜鸡水平的视角来记录学习理解的过程,见谅. 1.前言 产品使用vue+element作为前端框架.在功能开发过程中 ...
- vue 自定义指令的魅力
[第1103期]vue 自定义指令的魅力 点点 前端早读课 2017-11-08 前言 很多事情不能做过多的计划,因为计划赶不上变化.今日早读文章由富途@点点翻译分享. 正文从这开始- 在你初次接触一 ...
- Vue的指令和成员
目录 Vue的指令和成员 指令 表单 斗篷 条件 循环 成员 计算成员 监听成员 Vue的指令和成员 指令 表单 表单指令一般是和属性指令联合使用的,最常见的就是v-model="变量&qu ...
- vue自定义指令实例使用(实例说明自定义指令的作用)
在写vue项目的时候,我们经常需要对后台返回的数据进行大量的渲染操作,其中就包含了大量的对特殊数据的进一步处理,比如说时间戳.图片地址.特殊数据显示等等特殊数据处理改进. 其实遇到这种情况,通过Vue ...
随机推荐
- Linux安装h2数据库
安装H2数据库,为后面mybatisplus3J集成做铺垫 下载jar包 https://pan.baidu.com/s/1tPZQH5tum1CheDxumcN24g 运行jar包 [root@to ...
- SpringBoot注入配置文件的3种方法
方案1:@ConfigurationProperties+@Component 定义spring的一个实体bean装载配置文件信息,其它要使用配置信息是注入该实体bean /** * 将配置文件中配置 ...
- IoTClient开发3 - ModBusTcp协议客户端实现
前言 进过前面两章的介绍,今天开始正式的实战. 进制转换 很多朋友对于进制转换可能是在刚学计算机的时候有接触,后来做高级语言开发可能就慢慢忘记了.我们做工控开发的时候需要经常进行进制转换,这里和大家一 ...
- java的静态代理、jdk动态代理和cglib动态代理
Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...
- 【aliyun】学java,看这里,不迷茫!1460道Java热门问题
阿里极客公益活动: 或许你挑灯夜战只为一道难题 或许你百思不解只求一个答案 或许你绞尽脑汁只因一种未知 那么他们来了,阿里系技术专家来云栖问答为你解答技术难题了 他们用户自己手中的技术来帮助用户成长 ...
- [考试反思]1031csp-s模拟测试95:优势
假的三首杀.因为交文件所以他们都不往OJ上交. 假装是三首杀吧.嗯. 然而昨天还是没有AK.好像说是按照64位评测机的评测结果为准. 但是联赛省选的机子好像都是32位的?也就是和我们正在用的一致. 所 ...
- vue proxyTable代理 解决开发环境的跨域问题
如果我们项目请求的地址为 htttp://xxxx.com/a/b/c 可以设置代理为: dev:{ assetsSubDirectory: 'static',// 静态资源文件夹 assetsPub ...
- windsServer2008设置定时重启
点击“开始”——“管理工具”——“任务计划程序”. 右键“任务计划程序库”——“创建任务”. 输入计划名称.描述和安全选项(如下图). 点击触发器,点击“新建…”,输入计划周期和时间(如下图):无误后 ...
- spring security 简单入门
spring security 简单入门示例 一.概述 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架 . 其中最主要的安全操作有两 ...
- keeplived离线安装openssl-devel依赖包
转载自素文宅博客:https://blog.yoodb.com/yoodb/article/detail/1434 由于公司业务并发比较高需要高可用使用LVS keeplived.在linux系统ce ...