element-ui如何防止重复提交的方法步骤


Posted in Javascript onDecember 09, 2019

先说对话框(Dialog)里的表单提交

错误方案

说起错误方案,比如,点击提交按钮,本地验证,验证通过立即让按钮不可点,这些没问题,而我的错误点概括是:在某个最后执行的回调函数的最后一行,我做了2个操作:1,隐藏Dialog,2,让提交按钮可点击。

这个方案看似没问题,做到了让对话框消失,又保证下一次打开Dialog之后,提交按钮是可点击的。但它错误在于:隐藏Dialog是一个动画过程,并不是瞬间消失,所以按钮恢复可点击之后,Dialog还没有彻底隐藏,所以只要你点得够快,就可以多点几次按钮。

正确方案

  1. 早在打开对话框的时候,将提交按钮可点击。做法是在<el-dialog>上加入open事件函数:@open="submitButtonDisabled = false",其中submitButtonDisabled是我控制提交按钮的变量,你可以改成你自己用的。
  2. 点击之后验证,通过则立即按钮不可点(this.submitButtonDisabled = true),不通过则不做任何针对按钮的处理。(这是铁律,下面会经常看到)
  3. 验证通过的话,最后执行的某个回调函数的最后一行,隐藏对话框。比如this.dialogFormVisible = false,这个变量你也要改成自己用的。

它的核心是2点:早在打开对话框的时候就让提交按钮可点击;验证通过的话,最后的回调函数不应该去管提交按钮恢复可点击的事,而是放到下一次打开对话框的时候才让提交按钮可点击。

再说不涉及对话框的提交

不涉及对话框,比如按钮在页面上直接存在,又分三种情况:

  1. 点击之后不跳转,但按钮消失
  2. 点击之后不跳转,按钮也不消失
  3. 点击之后跳转页面

即便是跳转页面,也是需要时间的,这个期间一样可以重复提交。不跳转页面的话,重复提交就更容易发生了。怎么办?

情况1:点击之后不跳转,但按钮消失

这种情况出现在小型提交场合,比如在表格中修改数据,表格中的某个单元格有一个修改按钮,点击之后按钮消失,只留下数据自己,而且,不允许有成功提示框,因为毕竟是小型提交场合,而且提交按钮消失就已经代表了成功。

element-ui如何防止重复提交的方法步骤

这就是三种不同的状态,依次是无数据时、编辑状态时、有数据时

这种情况的处理方案很简单:

  1. 点击之后验证,通过则立即不可点,不通过则不针对按钮处理
  2. 服务器返回结果之后,保存成功则按钮消失,保存失败则按钮依旧存在。无论成功失败,按钮都要变成可点击。由于这里按钮消失是瞬间发生,没有动画过程,所以就算按钮变回可点击,也因为它已经消失,因此不会造成重复提交。

这里引出一个问题,就是表格中的小型提交场合,Save按钮会有一竖列,如何准确给某个按钮设置不可点击呢?可以这样:

  1. 从服务器获取表格数据之后要做一步加工,遍历数据,加上item.saveButtonDisabled = false之类的语句,然后再赋值给data子对象。
  2. 给按钮绑定方法时,要传参数,element-ui中可以传row,也就是@click="clickSave(row)"。
  3. 点击按钮先验证数据,通过则立即row.saveButtonDisabled = true,ajax回调之后就row.saveButtonDisabled = false,就可以了。

情况2:点击之后不跳转,按钮也不消失

比如一个表单直接显示在网页中,无论提交多少次,页面都纹丝不动。

这时候再按照上面的情况的处理方案就行不通了,因为比如1秒数据就走了一个来回,那么我每1.1秒点击一次鼠标就可以无限提交下去。

处理方案:

首先,应该避免做这种“无论提交多少次,页面都纹丝不动”的设定,应该做到ajax返回OK之前,提交按钮是失效的,OK了就让提交按钮可点击,并且要弹个提示框,这个提示框就可以阻断连续提交。这里面还是有一个问题就是,如果在返回OK之后、提示框使用了Dialog,那么弹出的过程中点击了提交按钮,依然是可以提交的,因为还是那个动画问题,提示框弹出是需要时间的。这时候也好办,别用Dialog,用MessageBox就可以了,它有回调函数,在回调函数里让提交按钮可点击,就行了。

然后,如果有些场景下,必须“页面纹丝不动”,提示框都不允许有,那么这时候可以采用节流机制,也就是说按钮点击之后3秒内就不允许再点击,即便上一次的提交已经1秒完成。方案是:

点击之后验证,通过则立即不可点,不通过则不针对按钮处理

通过之后,设个变量resolve = 0,同时执行ajax以及setInterval(fn, 1000),由fn负责判断:

  1. 当ajax返回OK,则resolve += 1
  2. 当ajax返回错误,则resolve += 2
  3. 当延迟3秒,则resolve += 1
  4. 当resolve >= 2则让按钮可点,且clearInterval

这是一种比较奇葩的算法,也就是说,OK和3秒同时具备的话,resolve为2,则让按钮可点,只错误的话,resolve会等于或大于2,就立即让按钮可点,同时报错。

如果ajax超时,比如断网了,那么也会返回错误,只不过这个错误可能会10秒/20秒/30秒/60秒之后返回(根据你的ajax配置),其实这也属于上面说的ajax返回错误,所以依然是适用的。

情况3:点击之后跳转页面

点击之后跳转页面也很常见,无奈跳转页面也是需要时间的,也可以多次提交。怎么办?

  1. 页面打开时,让按钮可点(跟对话框场景道理一样)
  2. 点击之后验证,通过则立即不可点,不通过则不针对按钮处理
  3. 通过之后,当ajax返回OK,则立即跳转(不去恢复成可点),这样鼠标重复点击多少次都没事。当ajax返回错误,则弹出错误,且按钮恢复为可点

为什么当ajax返回错误后不防范重复点击?

因为我们将普通用户定义为:非常喜欢点击鼠标,但思维正常的人,既然用户已经看到了提示错误,当然就不会再重复点击了,况且错误提示往往会是MessageBox,它会阻止重复提交。我们更多的是考虑如何防范鼠标连击的情况。

恶意重复提交

前端永远是防君子,难防小人的,恶意攻击者想要恶意重复提交的话,一定会直接攻击后端,所以上面所有措施一律无效,还需要后端做措施,这里就不多说了。

最后说说axios拦截提交

根据网上一些教程,axios拦截提交其实是有问题的:

  • 它的拦截,其实是在重复提交的时候拦截前一次的提交,而我们通常认为,应该拦截后面发生的所有提交。
  • ajax速度有时候非常快,根本来不及拦截。
  • api写的太晦涩了。
  • 需要考虑多种情况,比如有的时候允许3秒提交一次,有的时候随时可以提交,拦截规则越搞越复杂。

利用URL和params特征判断是否能解决问题

比如,规定时间内(比如3秒),或者不设规定时间,只要向同一个URL发送同样的数据,就禁止发送。表面上看起来,似乎防范重复提交的本质就是要阻止同样的数据重复发送,但是这里面依然有问题。

比如规定时间3秒内不能发送同样数据,那么,如果是axios全局做判断,就要考虑,会不会有其他的ajax穿插在3秒里面,所以说,每次准备ajax发送请求,就要遍历追溯前三秒发送过的请求里有没有重复请求,所以始终要记录每一次请求,还要记下时间戳,似乎有些麻烦。如果只是根据每个提交事件做统计,其实道理一样,也是要遍历。

而且,如果用户每隔4秒点击一次,而ajax返回用时5秒,那么第二次请求就真的会发出去。

如果不规定时间,只要发送同样数据就一定拒绝,那么,如果用户不经意间,在3分钟内2次提交了相同的内容,允许不允许提交呢?比如用户3分钟中了2次奖,填了2次个人信息,允许提交吗?按说应该允许,因为有些场合确实可能存在用户提交同样内容,但是,现在禁止提交,就阻截了正常提交。最后只能是把拦截规则越搞越复杂。

当然,最为致命的问题是:用户体验莫名其妙。无论什么技术,都要把用户体验放在第一位,如果开发者不去管按钮能否点击,只做背后的拦截逻辑,也就是始终让按钮能点击,用户毫无疑问会有很大概率多次点击,如果赶上ajax慢,用户会疯狂点击,最后疯掉也不夸张,这不是我们想要的结果。

所以说前端拦截重复提交的最好办法一定是用正确逻辑控制按钮的disabled。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 获取页面的高度及滚动条的位置的代码
May 06 Javascript
js实现兼容IE6与IE7的DIV高度
May 13 Javascript
jQuery的attr与prop使用介绍
Oct 10 Javascript
JavaScript中通过prototype属性共享属性和方法的技巧实例
Mar 13 Javascript
三分钟带你玩转jQuery.noConflict()
Feb 15 Javascript
JQUERY的AJAX请求缓存里的数据问题处理
Feb 23 Javascript
JavaScript实现阿拉伯数字和中文数字互相转换
Jun 12 Javascript
js实现可键盘控制的简单抽奖程序
Jul 13 Javascript
详解vue更改头像功能实现
Apr 28 Javascript
使用原生js编写一个简单的框选功能方法
May 13 Javascript
Javascript数组方法reduce的妙用之处分享
Jun 10 Javascript
微信小程序分享小程序码的生成(带参数)以及参数的获取
Mar 25 Javascript
js刷新页面location.reload()用法详解
Dec 09 #Javascript
vue 实现websocket发送消息并实时接收消息
Dec 09 #Javascript
Vue extend的基本用法(实例详解)
Dec 09 #Javascript
vue基于v-charts封装双向条形图的实现代码
Dec 09 #Javascript
微信小程序图片加载失败时替换为默认图片的方法
Dec 09 #Javascript
vue如何使用async、await实现同步请求
Dec 09 #Javascript
Vue替代marquee标签超出宽度文字横向滚动效果
Dec 09 #Javascript
You might like
利用PHP和AJAX创建RSS聚合器的代码
2007/03/13 PHP
PHP排序算法类实例
2015/06/17 PHP
详解Yii2.0 rules验证规则集合
2017/03/21 PHP
php判断str字符串是否是xml格式数据的方法示例
2017/07/26 PHP
PHP pthreads v3下的Volatile简介与使用方法示例
2020/02/21 PHP
不错的asp中显示新闻的功能
2006/10/13 Javascript
js判断浏览器类型为ie6时不执行
2014/06/15 Javascript
使用jQuery的attr方法来修改onclick值
2014/07/07 Javascript
angularJS 入门基础
2015/02/09 Javascript
JavaScript计算两个日期时间段内日期的方法
2015/03/16 Javascript
JavaScript使用shift方法移除素组第一个元素实例分析
2015/04/06 Javascript
js控制多图左右滚动切换效果代码分享
2015/08/26 Javascript
JavaScript的ExtJS框架中表格的编写教程
2016/05/21 Javascript
深入理解JavaScript中为什么string可以拥有方法
2016/05/24 Javascript
jQuery插件扩展extend的简单实现原理
2016/06/24 Javascript
angular实现spa单页面应用实例
2017/07/10 Javascript
vue2.0实现音乐/视频播放进度条组件
2018/06/06 Javascript
微信公众平台 发送模板消息(Java接口开发)
2019/04/17 Javascript
微信小程序swiper使用网络图片不显示问题解决
2019/12/13 Javascript
如何手写一个简易的 Vuex
2020/10/10 Javascript
springboot+vue实现文件上传下载
2020/11/17 Vue.js
Python 网络编程起步(Socket发送消息)
2008/09/06 Python
35个Python编程小技巧
2014/04/01 Python
Python写的创建文件夹自定义函数mkdir()
2014/08/25 Python
Python解析excel文件存入sqlite数据库的方法
2016/11/15 Python
对python过滤器和lambda函数的用法详解
2019/01/21 Python
django url到views参数传递的实例
2019/07/19 Python
python根据时间获取周数代码实例
2019/09/30 Python
Python3将jpg转为pdf文件的方法示例
2019/12/13 Python
python 中的[:-1]和[::-1]的具体使用
2020/02/13 Python
css3动画效果抖动解决方法
2018/09/03 HTML / CSS
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
2018/01/03 HTML / CSS
Canvas系列之滤镜效果
2019/02/12 HTML / CSS
美国智能家居专家:tink
2019/06/04 全球购物
民主评议党员登记表自我评价
2014/10/20 职场文书
PyTorch梯度裁剪避免训练loss nan的操作
2021/05/24 Python