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 Cookie显示用户上次访问的时间和次数
Dec 08 Javascript
jQuery1.5.1 animate方法源码阅读
Apr 05 Javascript
javascript不可用的问题探究
Oct 01 Javascript
jquery如何扑捉回车键触发的事件
Apr 24 Javascript
jquery+css3打造一款ajax分页插件(自写)
Jun 18 Javascript
a标签的href与onclick事件的区别详解
Nov 12 Javascript
你真的了解BOM中的history对象吗
Feb 13 Javascript
使用 jQuery 实现表单验证功能
Jul 05 jQuery
使用vue-cli(vue脚手架)快速搭建项目的方法
May 21 Javascript
「中高级前端面试」JavaScript手写代码无敌秘籍(推荐)
Apr 08 Javascript
详解小程序如何避免多次点击,重复触发事件
Apr 08 Javascript
解决Layui数据表格显示无数据提示的问题
Nov 14 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
解决phpmyadmin中文乱码问题。。。
2007/01/18 PHP
thinkphp框架实现数据添加和显示功能
2016/06/29 PHP
php mysql PDO 查询操作的实例详解
2017/09/23 PHP
php 与 nginx 的处理方式及nginx与php-fpm通信的两种方式
2018/09/28 PHP
javascript 对象的定义方法
2007/01/10 Javascript
借用Google的Javascript API Loader来加速你的网站
2009/01/28 Javascript
JavaScript高级程序设计 读书笔记之八 Function类及闭包
2012/02/27 Javascript
Jquery实现列表(隔行换色,全选,鼠标滑过当前行)效果实例
2013/06/09 Javascript
ie浏览器使用js导出网页到excel并打印
2014/03/11 Javascript
如何用jquery控制表格奇偶行及活动行颜色
2014/04/20 Javascript
使用js dom和jquery分别实现简单增删改
2014/09/11 Javascript
探究Javascript模板引擎mustache.js使用方法
2016/01/26 Javascript
JavaScript类的写法
2016/09/17 Javascript
AngularJS实现给动态生成的元素绑定事件的方法
2016/12/14 Javascript
jquery操作select取值赋值与设置选中实例
2017/02/28 Javascript
jQuery实现简单的回到顶部totop功能示例
2017/10/16 jQuery
ligerUI---ListBox(列表框可移动的实例)
2017/11/28 Javascript
移动前端图片压缩上传的实例
2017/12/06 Javascript
vue 引入公共css文件的简单方法(推荐)
2018/01/20 Javascript
详解解决使用axios发送json后台接收不到的问题
2018/06/27 Javascript
vuejs2.0运用原生js实现简单拖拽元素功能
2020/08/21 Javascript
微信小程序入门之广告条实现方法示例
2018/12/05 Javascript
深入了解Hybrid App技术的相关知识
2019/07/17 Javascript
Python 序列化 pickle/cPickle模块使用介绍
2014/11/30 Python
Python使用urllib2模块实现断点续传下载的方法
2015/06/17 Python
Python面向对象编程中关于类和方法的学习笔记
2016/06/30 Python
回调函数的意义以及python实现实例
2017/06/20 Python
浅谈tensorflow 中的图片读取和裁剪方式
2020/06/30 Python
CSS3系列教程:背景图片(背景大小和多背景图) 应用说明
2012/12/19 HTML / CSS
css 如何让背景图片拉伸填充避免重复显示
2013/07/11 HTML / CSS
美国特价机票专家:Airfarewatchdog
2018/01/24 全球购物
编写类String的构造函数、析构函数和赋值函数
2012/05/29 面试题
优秀学生获奖感言
2014/02/15 职场文书
大学生求职信怎么写
2015/03/19 职场文书
vue使用节流函数的踩坑实例指南
2021/05/20 Vue.js
基于Redis6.2.6版本部署Redis Cluster集群的问题
2022/04/01 Redis