前端防止用户重复提交js实现代码示例


Posted in Javascript onSeptember 07, 2018

背景

前端在向后端进行数据提交的时候,通常会需要在第一次提交返回前,阻止用户在快速点击发送二次请求,即防止重复提交,最简单的方法是使用标志参数或者 class 元素控制,但缺点是,每个控制重复提交的地方都需要加上这个逻辑,重复性太强,且控制逻辑不统一。

目前前端使用的是http协议,所以提交方式为两种

  • 异步提交,使用jQuery.ajax()
  • form 表单同步提交

下面这篇文章将给大家详细介绍关于这两种方法实现的方法示例,下面话不多说了,来随着小编一起看看详细的介绍吧

异步防重复提交的方案如下

通过 jQuery 提供的 ajaxPrefilter 方法,将在请求提交之前进行过滤,仅保留第一次请求,后续的请求 abort 阻止掉,具体实现代码如下

/**
 * _pendingRequests = {
 * 'http:xxx.xxxx.do':['domain=P2P','xxxx=aaa'],
 * 'http:xxx.yyyy.do':['domain=P3P','xxxx=bbb']
 * }
 * 该对象的 key 是请求的 url ,value 是由请求参数转化成的字符串数组
 */
var _pendingRequests = {};
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
 var p_item = { //保存请求请求的url
 key:options.url,
 index:0
 },
 dataArray = options.data ? options.data.split('&') : [];
 compareData = function(beforD,afterD) {
 //当url相同时,以此比较保存的参数对象,若参数对象相同,则返回false,若第一个就相同,则跳出循环
 // 反之说明当前参数对象列表中没有与将要提交的参数相同,则可看为不同的请求,返回true,允许发起请求
 var result = false;
 for(var i=0;i<beforD.length;i++){
 if(beforD[i]){
  result = false;
  var beforData = beforD[i];
  for(var j=0;j<beforData.length;j++){
  if(afterD[j] !== beforData[j]){
  result = true;
  break;
  }
  }
  if (!result){
  break;
  }
 }else {
  result = true;
  continue;
 }
 }
 return result;
 };

 //若请求队列中不存在或者同一个请求不同参数,且不为html后缀,则加入队列中
 if (( !_pendingRequests[p_item.key] || compareData(_pendingRequests[p_item.key],dataArray) ) && p_item.key.indexOf('.html') === -1) {
 //给 index 赋值是因为请求是异步返回的,index用于标记第一个请求
 if(_pendingRequests[p_item.key]){
 p_item.index = _pendingRequests[p_item.key].push(dataArray)-1;
 } else{
 _pendingRequests[p_item.key] = [dataArray];
 p_item.index = 0;
 }
 } else if (p_item.key.indexOf('.html') === -1) {
 jqXHR.abort(); // 放弃后触发的重复提交,仅保留第一次提交
 //pendingRequests[key].abort(); // 放弃先触发的提交
 }
 var complete = options.complete;
 //请求完成
 options.complete = function(jqXHR, textStatus) {
 // 通过 key 和 index 获取成功返回的请求,将其值为 null ,下一次该请求便是在请求队列中便是新的一个请求
 _pendingRequests[p_item.key][p_item.index] = null;
 if ($.isFunction(complete)) {
 complete.apply(this, arguments);
 }
 };
});

jquery.ajaxprefilter官方文档

表单提交防重复提交的方案如下

表单的处理就稍微要麻烦点,但大致思路和异步的相同,等待第一次请求返回的同时,阻止后续触发的请求发送
首先基于jquery扩展了一个自定义的方法,如下

$.fn.preventDoubleSubmission = function() {
 $(this).on('submit', function(e) {
 var $form = $(this);
 // $form.data('submitted') 通过该变量判断请求的状态
 if ($form.data('submitted') === true) {
 //阻止请求
 e.preventDefault();
 } else {
 $form.data('submitted', true);
 if ($form.attr('target') === '_blank') {
 setTimeout(function() {
  $form.data('submitted', false);
 }, 800);
 }
 }
 });
 return this;
};

当表单初次提交时,通过 jQuery.data() 设置一个标志位,当表单重复提交时,判断设置的标志位,若是提交状态,将阻止表单的提交事件。当form.target = _blank 提交后打开新界面的情况,将在800毫秒后恢复原界面表单可提交状态。

为了方便对全站的表单提交统一处理,可对需要放重复提交的表单添加一个class preventDouble,在页面渲染后,统一加上事件监听

//扫描带有 preventDouble 标识的form表单
$(function() {
 var f = $('.contain form.preventDouble');
 for (var i=0;i<f.length;i++){
 $(f[i]).preventDoubleSubmission();
 }
});

小贴士

  • 提交按钮需使用 type='submit' ,因为监听的是表单的submit事件
  • 不建议多次监听submit事件,会导致放重复提交失效
  • 在表单提交前通常会有些表单检验的操作,所以当校验失败的时候,可以通过 event.preventDefault() 阻止表单提交

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jquery JSON的解析方式
Jul 25 Javascript
一个JS的日期格式化算法示例
Jul 31 Javascript
利用js读取动态网站从服务器端返回的数据
Feb 10 Javascript
JavaScript中的数据类型转换方法小结
Oct 26 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
Oct 27 Javascript
JS实现探测网站链接的方法【测试可用】
Nov 08 Javascript
jQuery Validate 相关参数及常用的自定义验证规则
Mar 06 Javascript
Javascript中类式继承和原型式继承的实现方法和区别之处
Apr 25 Javascript
jQuery 开发之EasyUI 添加数据的实例
Sep 26 jQuery
原生js实现移动端触摸轮播的示例代码
Dec 22 Javascript
JS使用正则表达式获取小括号、中括号及花括号内容的方法示例
Jun 01 Javascript
angular 表单验证器验证的同时限制输入的实现
Apr 11 Javascript
vue实现打印功能的两种方法
Sep 07 #Javascript
使用Angular-CLI构建NPM包的方法
Sep 07 #Javascript
详解如何构建一个Angular6的第三方npm包
Sep 07 #Javascript
vue2.0 可折叠列表 v-for循环展示的实例
Sep 07 #Javascript
Js中使用正则表达式验证输入是否有特殊字符
Sep 07 #Javascript
vue.js+element-ui动态配置菜单的实例
Sep 07 #Javascript
详解npm 配置项registry修改为淘宝镜像
Sep 07 #Javascript
You might like
PHP strtok()函数的优点分析
2010/03/02 PHP
PHP与C#分别格式化文件大小的代码
2011/05/14 PHP
PHP简单实现“相关文章推荐”功能的方法
2014/07/19 PHP
BOOM vs RR BO5 第二场 2.14
2021/03/10 DOTA
URL地址中的#符号使用说明
2011/02/12 Javascript
jquery获得下拉框值的代码
2011/08/13 Javascript
Jquery each方法跳出循环,并获取返回值(实例讲解)
2013/12/12 Javascript
js用typeof方法判断undefined类型
2014/07/15 Javascript
jQuery 中$(this).index与$.each的使用指南
2014/11/20 Javascript
详解Javascript动态操作CSS
2014/12/08 Javascript
JavaScript中的函数声明和函数表达式区别浅析
2015/03/27 Javascript
JS实现弹性菜单效果代码
2015/09/07 Javascript
JavaScript记录光标在编辑器中位置的实现方法
2016/04/22 Javascript
配置nodejs环境的方法
2017/05/13 NodeJs
JS+HTML5实现图片在线预览功能
2017/07/22 Javascript
详解使用Typescript开发node.js项目(简单的环境配置)
2017/10/09 Javascript
Nodejs实现爬虫抓取数据实例解析
2018/07/05 NodeJs
vue.js项目 el-input 组件 监听回车键实现搜索功能示例
2018/08/25 Javascript
javascript中数组的常用算法深入分析
2019/03/12 Javascript
分享8个JavaScript库可更好地处理本地存储
2020/10/12 Javascript
[00:52]玛尔斯技能全介绍
2019/03/06 DOTA
解决python3 json数据包含中文的读写问题
2018/05/10 Python
Python 安装第三方库 pip install 安装慢安装不上的解决办法
2019/06/18 Python
python 实现目录复制的三种小结
2019/12/04 Python
Python3爬虫里关于代理的设置总结
2020/07/30 Python
英国在线定做百叶窗网站:Make My Blinds
2020/08/17 全球购物
惠而浦美国官网:Whirlpool.com
2021/01/19 全球购物
美术毕业生求职信
2014/02/25 职场文书
法律进机关实施方案
2014/03/12 职场文书
党员领导干部廉洁从政承诺书
2014/03/27 职场文书
小学家长学校培训材料
2014/08/24 职场文书
2014年移动公司工作总结
2014/12/08 职场文书
学校食堂食品安全承诺书
2015/04/29 职场文书
民警忠诚教育心得体会
2016/01/23 职场文书
机关干部纪律作风整顿心得体会
2016/01/23 职场文书
CentOS 7安装mysql5.7使用XtraBackUp备份工具命令详解
2022/04/12 MySQL