更好一点的: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 ...
随机推荐
- 关于explorer.exe文件或目录已损坏的问题
2019-5-8 今天由于断电导致电脑异常关机,就出现了开机后屏幕是黑的,只显示鼠标,然后会有警告:explorer.exe目录或文件已损坏. 网上也有各种解决办法,但是都没有清楚,导致捣鼓了半天,首 ...
- DirectX9:基础篇 第一章 初始化Direct3D
一.简介 二.Direct3D类 1.创建D3D类 IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion); //Direct3D类的创建 IDirec ...
- 随机数产生器:Random.Next
Random类是一个产生伪随机数字的类,它的构造函数有两种,一个是直接New Random(),另外一个是New Random(Int32),前者是根据触发那刻的系统时间做为种子,来产生一个随机数字, ...
- Openmp编程练习
火车卖票 // OpenMP2.cpp : 定义控制台应用程序的入口点. // #include "stdio.h" #include "omp.h" #inc ...
- 明解C语言 入门篇 第二章答案
练习2-1 #include <stdio.h> int main() { int x; int y; int percent; puts("请输入两个整数"); pr ...
- 一位年轻而优秀的.NET开发者的成长点滴
一,社区的小圈子 今年3月的一次技术交流活动上,那是我们.NET技术社区第一次组织线下活动,由于没什么经验,所以活动组织得比较仓促,内容也比较一般,效果还是有点欠缺.当然,活动本身是必要的,这次活动上 ...
- H5与CSS3常用设置
1.设置div铺满全屏 对于一个div1,要使其属性height:100%生效,需要使其所有父元素,有确定的属性height.要铺满全屏,就是从html开始,所有的height为100%. 2.垂直居 ...
- Python3爬虫(3)_urllib.error
注:参照https://blog.csdn.net/c406495762/article/details/59488464 Learn_ERROR: urllib.error可以接收有urllib.r ...
- 程序员接私活经验总结,来自csdn论坛语录
以下为网上摘录,以做笔记: 可是到网上看看,似乎接私活也有很多不容易,技术问题本身是个因素,还有很多有技术的人接私活时被骗,或者是合作到最后以失败告终,所以想请有经验的大侠们出来指点一下,接私活是怎么 ...
- git log 附加命令归纳
git查看历史记录的时候查看每次提交的内容差异: git log -p git限制显示的条数 : git log -p -2 [-2] git简单显示每次提交做了哪些改动: git log --sta ...