更好一点的: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 ...
随机推荐
- intellij idea - Project Structure 项目结构详解(简单明了)
IDEA Project Structure 设置 可以点击 按钮,或者使用快捷键 Ctrl + Shift + Alt + S 打开 Project Structure .如下如所示: 项目的左 ...
- 二:Mysql库相关操作
1:系统数据库 information_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息.列信息.权限信息.字符信息等.performance_schema: My ...
- [考试反思]0801NOIP模拟测试11
8月开门红. 放假回来果然像是神志不清一样. 但还是要接受这个事实. 嗯,说好听点,并列rank#7. 说难听点,垃圾rank#18. 都不用粘人名就知道我是哪一个吧... 因为图片不能太长,所以就不 ...
- NOIP模拟 23
曾经有一段真挚的AK摆在skyh面前,但他一直意淫自己AK导致没有AK. 如果非要把这AK加一个期限的话,skyh一辈子都AK不了了. 论爆零选手的爆零原因 我说T3想到了能AC的思路但是爆零了有人同 ...
- python学习之【第九篇】:Python中的变量作用域
1.前言 Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的. 2.变量作用域 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python的作 ...
- 从BIO到Netty的演变
从BIO到Netty的演变 前言 计算机网络可以说是每个学计算机的都绕不过去的一道坎.计算机网络到底有多么重要,你走到大学图书馆的计算机部分,翻开那些什么<从零开始:黑客XXX>,< ...
- SpringBoot Web篇笔记(一)
摘要 文章是根据江南一点雨(松哥)的视频进行总结 江南一点雨博客 全局异常处理 通常情况下,我们都需要对自己定义的异常进行相应的处理.捕获指定的异常方式如下: @ControllerAdvice pu ...
- 机器学习之Anaconda介绍
Anaconda Distribution 最受欢迎的Python / R数据科学发行版 轻松安装1,400多个Python / R数据科学包并管理您的包,依赖项和 环境 - 只需单击一下按钮即可.免 ...
- 使用springcloud开发测试问题总结
使用springcloud开发测试 如下描述的问题,没有指明是linux部署的,都是在windows开发环境上部署验证发现的. Issue1配置客户端不使用配置中心 问题描述: 配置客户端使用配置中心 ...
- canvas与工作流的不解之缘
html的标签 <canvas>用于图形的绘制,通过脚本 (通常是JavaScript)来完成,canvas简而言之就是个画布.上一篇文章我们提到工作流的一个重要组成部分:流程建模,也就是 ...