Vue 利用指令实现禁止反复发送请求的两种方法


Posted in Javascript onSeptember 15, 2019

前端做后台管控系统,在某些接口请求时间过长的场景下,需要防止用户反复发起请求。

假设某场景下用户点击查询按钮后,后端响应需要长时间才能返回数据。那么要规避用户返回点击查询按钮无外乎是让用户无法在合理时间内再次点击按钮。实现方式也有好几种:

1、在按钮点击发起请求后,弹个蒙层,显示个loading,等请求数据返回了将蒙层隐藏掉。

2、在按钮点击发起请求后,将按钮禁用掉,同样等数据返回了将按钮禁用解除。

以上是比较常见的2种方案。

实现上最简单的肯定是在需要的页面种在请求前和拿到数据后,单独处理。这种方案优点仅仅是简单,但是每个需要处理的页面都要单独写一串重复的代码,哪怕利用mixin也要多不少冗余代码。

如果是利用指令的方式仅仅需要在合适的地方加上个一条v-xxxx,其他都在指令的逻辑内统一处理。

以第二种方式为例:

clickForbidden.js

let forbidClick = null;
export default {
 bind(e) {
  const el = e;
  let timer = null;
  forbidClick = () => {
   el.disabled = true;
   el.classList.add('is-disabled');
   timer = setTimeout(() => {
   el.disabled = false; 
    el.classList.remove('is-disabled');
   }, 3000);
  };
  el.addEventListener('click', forbidClick);
 },
 unbind() {
  document.removeEventListener('click', forbidClick);
 },
};

指令的逻辑很简单,当按钮插入到DOM节点后,添加一个监听click的事件,当按钮点击后,就将按钮禁用,并加上一个禁用样式,并在3s后将该按钮解除禁用。

再考虑请求,以axios为例:

api.js

import axios from 'axios';
export baseURL = 'xxxx';
const api = axios.create({
 baseURL,<br data-filtered="filtered"> timeout: 3000,
});
/* 记录当前请求是否完成 */
window.currentResq = {
 done: true,
 config: {},
};
api.interceptors.request.use(function(config) {
 clearTimeout(resqTimer);
 window.currentResq = {
  done: false,
  config,
 };
 // 接口请求时长超过3s,则视为完成,不管请求结果成功或失败
 resqTimer = setTimeout(() => {
  window.currentResq = {
   done: true,
   config: {},
  };
 }, 3000);
});
api.interceptors.response.use(function(response) {
 const { config } = window.currentResq;
 const { url, method, data } = response.config;
 if (config.url === url && config.method === method && config.data === data) {
  clearTimeout(resqTimer);
  window.currentResq.done = true;
 }
 return response;
}, function (error) {
 return error;
});
 
export default api;

用一个全局的currentResq来作为请求是否完成的标志。在axios请求拦截器种,将当前请求的数据记录在currentResq中,并将done设置为false。在axios响应拦截器中,约定url,method,data3个参数一样时,就是当前currentResq中记录的请求返回数据,并将done设置为true。

同样的在指令逻辑中加入一个轮询监听currentResq的done是否完成。

clickForbidden.js 

let forbidClick = null;
export default {
 bind(e) {
  const el = e;
  let timer = null;
  forbidClick = () => {
   el.disabled = true;
   el.classList.add('is-disabled');
   timer = setInterval(() => {
    if (window.currentResq.done) {
     clearInterval(timer);
     el.disabled = false;
     el.classList.remove('is-disabled');
    }
   }, 500);
  };
  el.addEventListener('click', forbidClick);
 },
 unbind() {
  document.removeEventListener('click', forbidClick);
 },
};

这样就实现了只要在按钮上加上了v-clickForbidden。按钮点击后就会被禁用,仅当某个请求返回数据或者3s后将按钮的禁用解除。

现在仅仅考虑按钮一次仅发送了一个请求的场景,在currentResq中也可以用一个数据来记录请求。

总结

以上所述是小给大家介绍的Vue 利用指令实现禁止反复发送请求的两种方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
为jquery的ajaxfileupload增加附加参数的方法
Mar 04 Javascript
AngularJS监听路由的变化示例代码
Sep 23 Javascript
jQuery实现简单漂亮的Nav导航菜单效果
Mar 29 jQuery
详解vue嵌套路由-query传递参数
May 23 Javascript
JS图片预加载插件详解
Jun 21 Javascript
分享vue.js devtools遇到一系列问题
Oct 24 Javascript
vue使用技巧及vue项目中遇到的问题
Jun 04 Javascript
vue打包相关细节整理(小结)
Sep 28 Javascript
使用nvm和nrm优化node.js工作流的方法
Jan 17 Javascript
图文详解vue框架安装步骤
Feb 12 Javascript
简单了解vue中的v-if和v-show的区别
Oct 08 Javascript
如何通过Proxy实现JSBridge模块化封装
Oct 22 Javascript
解决layui调用自定义方法提示未定义的问题
Sep 14 #Javascript
layui使用label标签的方法
Sep 14 #Javascript
使用layui定义一个模块并使用的例子
Sep 14 #Javascript
基于Layui自定义模块的使用方法详解
Sep 14 #Javascript
解决layui的form里的元素进行动态生成,验证失效的问题
Sep 14 #Javascript
浅谈layui使用模板引擎动态渲染元素要注意的问题
Sep 14 #Javascript
Layui Form 自定义验证的实例代码
Sep 14 #Javascript
You might like
PHP使用header()输出图片缓存实例
2014/12/09 PHP
详解PHP中的Traits
2015/07/29 PHP
thinkPHP使用pclzip打包备份mysql数据库的方法
2016/04/30 PHP
PHP获取redis里不存在的6位随机数应用示例【设置24小时过时】
2017/06/07 PHP
CentOS7系统搭建LAMP及更新PHP版本操作详解
2020/03/26 PHP
学习JavaScript设计模式之模板方法模式
2016/01/20 Javascript
javascript特殊日历控件分享
2016/03/07 Javascript
Bootstrap教程JS插件滚动监听学习笔记分享
2016/05/18 Javascript
JS简单实现无缝滚动效果实例
2016/08/24 Javascript
laravel5.4+vue+element简单搭建的示例代码
2017/08/29 Javascript
NodeJs 实现简单WebSocket即时通讯的示例代码
2019/08/05 NodeJs
微信小程序实现上拉加载功能示例【加载更多数据/触底加载/点击加载更多数据】
2020/05/29 Javascript
Electron+vue从零开始打造一个本地播放器的方法示例
2020/10/27 Javascript
[55:23]VGJ.T vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
[03:12]完美世界DOTA2联赛PWL DAY9集锦
2020/11/10 DOTA
MySQL中表的复制以及大型数据表的备份教程
2015/11/25 Python
Python实现的knn算法示例
2018/06/14 Python
python在html中插入简单的代码并加上时间戳的方法
2018/10/16 Python
python http基本验证方法
2018/12/26 Python
python对矩阵进行转置的2种处理方法
2019/07/17 Python
Python爬虫实现“盗取”微信好友信息的方法分析
2019/09/16 Python
Python图像处理库PIL的ImageEnhance模块使用介绍
2020/02/26 Python
美国摄影爱好者购物网站:Focus Camera
2016/10/21 全球购物
New Balance加拿大官方网站:运动鞋和健身服装
2018/11/19 全球购物
西班牙多品牌鞋店连锁店:Krack
2018/11/30 全球购物
UNIONBAY官网:美国青少年服装品牌
2019/03/26 全球购物
MAC彩妆澳洲官网:M·A·C AU
2021/01/17 全球购物
高一新生军训感言
2014/03/02 职场文书
2014七年级班主任工作总结
2014/12/05 职场文书
2015年五四青年节活动总结
2015/02/10 职场文书
伊索寓言读书笔记
2015/06/30 职场文书
2016年主题党日活动总结
2016/04/05 职场文书
学长教您写论文:经验总结
2019/07/09 职场文书
pytorch中[..., 0]的用法说明
2021/05/20 Python
python中24小时制转换为12小时制的方法
2021/06/18 Python
Python各协议下socket黏包问题原理
2022/04/12 Python