前端防止用户重复提交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 UI 应用不同Theme的办法
Sep 12 Javascript
js中的setInterval和setTimeout使用实例
May 09 Javascript
复制网页内容,粘贴之后自动加上网址的实现方法(脚本之家特别整理)
Oct 16 Javascript
javascript RegExp 使用说明
May 21 Javascript
webpack实现热更新(实施同步刷新)
Jul 28 Javascript
把vue-router和express项目部署到服务器的方法
Feb 21 Javascript
详解如何在vue-cli中使用vuex
Aug 07 Javascript
Vuerouter的beforeEach与afterEach钩子函数的区别
Dec 26 Javascript
vue elementUI 表单校验功能之数组多层嵌套
Jun 04 Javascript
js实现多张图片每隔一秒切换一张图片
Jul 29 Javascript
微信小程序缓存支持二次开发封装实现解析
Dec 16 Javascript
layui实现显示数据表格、搜索和修改功能示例
Jun 03 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 minixml详解
2008/07/19 PHP
PHP实现基于文本的摩斯电码生成器
2016/01/11 PHP
PHP单例模式详解及实例代码
2016/12/21 PHP
Js 订制自己的AlertBox(信息提示框)
2009/01/09 Javascript
使用jQuery Ajax功能时需要注意的一个问题(内存溢出)
2012/05/30 Javascript
JS 控件事件小结
2012/10/31 Javascript
JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
2014/08/16 Javascript
Python脚本后台运行的几种方式
2015/03/09 Javascript
JavaScript实现页面5秒后自动跳转的方法
2015/04/16 Javascript
javascript中callee与caller的区别分析
2015/04/20 Javascript
MVVM模式中ViewModel和View、Model有什么区别?
2015/06/19 Javascript
详解javascript中原始数据类型Null和Undefined
2015/12/17 Javascript
JavaScript中两个字符串的匹配
2016/06/08 Javascript
javascript实现的左右无缝滚动效果
2016/09/19 Javascript
javascript垃圾收集机制的原理分析
2016/12/08 Javascript
JS随机排序数组实现方法分析
2017/10/11 Javascript
浅谈vue2 单页面如何设置网页title
2017/11/08 Javascript
JavaScript中的高级函数
2018/01/04 Javascript
使用puppeteer破解极验的滑动验证码
2018/02/24 Javascript
AngularJS监听ng-repeat渲染完成的方法
2018/03/20 Javascript
js canvas实现红包照片效果
2018/08/21 Javascript
vue 解决mintui弹窗弹起来,底部页面滚动bug问题
2020/11/12 Javascript
python实现发送邮件及附件功能
2021/03/02 Python
python TKinter获取文本框内容的方法
2018/10/11 Python
设置python3为默认python的方法
2018/10/31 Python
python仿evething的文件搜索器实例代码
2019/05/13 Python
python绘制多个子图的实例
2019/07/07 Python
如何使用python实现模拟鼠标点击
2020/01/06 Python
django 利用Q对象与F对象进行查询的实现
2020/05/15 Python
Ralph Lauren意大利官方网站:时尚界最负盛名的品牌之一
2018/10/18 全球购物
彪马日本官网:PUMA日本
2019/01/31 全球购物
KOHLER科勒美国官网:国际著名卫浴橱柜领先品牌
2020/06/27 全球购物
广告学专业求职信
2014/06/19 职场文书
离职证明标准格式
2014/09/15 职场文书
房地产财务经理岗位职责
2015/04/08 职场文书
长征观后感
2015/06/09 职场文书