前端防止用户重复提交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中输入验证中一个不错的效果
Aug 21 Javascript
JavaScript获取文本框内选中文本的方法
Feb 20 Javascript
javascript实现的简单计时器
Jul 19 Javascript
JavaScript变量的作用域全解析
Aug 14 Javascript
iframe高度自适应及隐藏滚动条的实例详解
Sep 29 Javascript
原生JavaScript实现Ajax异步请求
Nov 19 Javascript
解决vue打包之后静态资源图片失效的问题
Feb 21 Javascript
vue引用js文件的多种方式(推荐)
May 17 Javascript
微信小程序动态生成二维码的实现代码
Jul 25 Javascript
vue-cli2打包前和打包后的css前缀不一致的问题解决
Aug 24 Javascript
vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单
Nov 29 Javascript
JavaScript函数的特性与应用实践深入详解
Dec 30 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
php5.3 废弃函数小结
2010/05/16 PHP
关于查看MSSQL 数据库 用户每个表 占用的空间大小
2013/06/21 PHP
CodeIgniter生成静态页的方法
2016/05/17 PHP
PHP模拟http请求的方法详解
2016/11/09 PHP
详解PHP使用Redis存储session时的一个Warning定位
2017/07/05 PHP
PHP实现的日历功能示例
2018/09/01 PHP
PHP实现递归的三种方法
2020/07/04 PHP
使用jQuery同时控制四张图片的伸缩实现代码
2013/04/19 Javascript
js 将json字符串转换为json对象的方法解析
2013/11/13 Javascript
简单的邮箱登陆的提示效果类似于yahoo邮箱
2014/02/26 Javascript
jquery数组封装使用方法分享(jquery数组遍历)
2014/03/25 Javascript
jquery 页眉单行信息滚动显示实现思路及代码
2014/06/26 Javascript
5个书写JavaScript代码的坏习惯,看看你中枪了没?
2014/11/06 Javascript
基于JavaScript的操作系统你听说过吗?
2016/01/28 Javascript
jQuery EasyUI右键菜单实现关闭标签/选项卡
2016/10/10 Javascript
js定时器实例分享
2016/12/20 Javascript
微信小程序开发之Tabbar实例详解
2017/01/09 Javascript
js中数组插入、删除元素操作的方法
2017/02/15 Javascript
详解如何使用koa实现socket.io官网的例子
2018/11/04 Javascript
Vue实现一个无限加载列表功能
2018/11/13 Javascript
小程序云开发教程如何使用云函数实现点赞功能
2019/05/18 Javascript
vue开发移动端底部导航条功能
2020/04/08 Javascript
解读Django框架中的低层次缓存API
2015/07/24 Python
Python面向对象原理与基础语法详解
2020/01/02 Python
英国标志性奢侈品牌:Burberry
2016/07/28 全球购物
西班牙英格列斯百货英国官网:El Corte Inglés英国
2017/10/30 全球购物
Lookfantastic香港官网:英国知名美妆购物网站
2018/06/19 全球购物
澳大利亚波西米亚风连衣裙在线商店:Fortunate One
2019/04/01 全球购物
写给学生的新学期寄语
2014/01/18 职场文书
岗位廉政承诺书
2014/03/27 职场文书
原料仓仓管员岗位职责
2014/07/08 职场文书
法英专业大学生职业生涯规划范文:衡外情,量己力!
2014/09/23 职场文书
作息时间调整通知
2015/04/22 职场文书
浅谈如何提高PHP代码的质量
2021/05/28 PHP
react antd实现动态增减表单
2021/06/03 Javascript
三星 3nm 芯片将于第二季度开始量产
2022/04/29 数码科技