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 event 事件解析
Jan 31 Javascript
js设置cookie过期及清除浏览器对应名称的cookie
Oct 24 Javascript
动态添加option及createElement使用示例
Jan 26 Javascript
javascript跨域的4种方法和原理详解
Apr 08 Javascript
jQuery实现的漂亮表单效果代码
Aug 18 Javascript
JS实现选项卡实例详解
Nov 17 Javascript
jQuery的事件预绑定
Dec 05 Javascript
Ionic+AngularJS实现登录和注册带验证功能
Feb 09 Javascript
jQuery插件ContextMenu自定义图标
Mar 15 Javascript
Puppeteer环境搭建的详细步骤
Sep 21 Javascript
vue递归组件实战之简单树形控件实例代码
Aug 27 Javascript
leaflet加载geojson叠加显示功能代码
Feb 21 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)
2013/06/21 PHP
深入PHP许愿墙模块功能分析
2013/06/25 PHP
PHP使用range协议实现输出文件断点续传代码实例
2014/07/04 PHP
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
2019/12/01 PHP
用js模拟JQuery的show与hide动画函数代码
2010/09/20 Javascript
在新窗口打开超链接的方法小结
2013/04/14 Javascript
禁止选中文字兼容IE、Chrome、FF等
2013/09/04 Javascript
jquery easyui 结合jsp简单展现table数据示例
2014/04/18 Javascript
在其他地方你学不到的jQuery小贴士和技巧(欢迎收藏)
2016/01/20 Javascript
基于js实现的限制文本框只可以输入数字
2016/12/05 Javascript
JavaScript字符串对象
2017/01/14 Javascript
完美解决UI-Grid表格元素中多个空格显示为一个空格的问题
2017/04/25 Javascript
Javascript创建类和对象详解
2017/05/31 Javascript
全面解析Node.js 8 重要功能和修复
2017/06/02 Javascript
javascript实现非常简单的小数取整功能示例
2017/06/13 Javascript
Vue2.0用 watch 观察 prop 变化(不触发)
2017/09/08 Javascript
VUE 解决mode为history页面为空白的问题
2019/11/01 Javascript
vue实现element表格里表头信息提示功能(推荐)
2019/11/20 Javascript
jQuery实现简易QQ聊天框
2020/02/10 jQuery
[00:55]2015国际邀请赛中国区预选赛5月23日——28日约战上海
2015/05/25 DOTA
Python2.x中str与unicode相关问题的解决方法
2015/03/30 Python
在Python的Django框架中调用方法和处理无效变量
2015/07/15 Python
《Python学习手册》学习总结
2018/01/17 Python
用python建立两个Y轴的XY曲线图方法
2019/07/08 Python
基于Python数据分析之pandas统计分析
2020/03/03 Python
python将字典内容写入json文件的实例代码
2020/08/12 Python
Marriott中国:万豪国际酒店查询预订
2016/09/02 全球购物
优秀学生干部个人的自我评价
2013/10/04 职场文书
个人实用简单的自我评价
2013/10/19 职场文书
计算机学生求职信范文
2014/01/30 职场文书
初中同学聚会邀请函
2014/02/03 职场文书
标准的毕业生自荐信
2014/04/20 职场文书
孔子观后感
2015/06/08 职场文书
骆驼祥子读书笔记
2015/06/26 职场文书
服装店员工管理制度
2015/08/07 职场文书
vue3语法糖内的defineProps及defineEmits
2022/04/14 Vue.js