按钮重复点击解决方案

防止重复提交,通用的思路,就是当用户点击提交按钮后,在浏览器中用JS将按钮disable掉,从而阻止用户继续点击该按钮,实现防止重复提交的目的。网上防止重复提交的文章已经不少了,为啥我还要写呢,显然我不是吃饱了撑的。。。最近一个客户,老抱怨每个月总有几条重复的业务数据;但创建该业务数据的页面,我们已经应用了常规的防重复提交技术,为啥还这样呢……

1. 常规防重复提交
<asp:Button runat="server" ID="btnPostBack1" Text="按我1" UseSubmitBehavior="false" OnClientClick="this.disabled=true;this.form.submit();"/>

这里需要注意的是:
(1). UseSubmitBehavior="false" :需要设置成false,这样生成了个的input的类型才是button;如果用默认的true,生成的input的类型为submit,postback到服务器端,将不会触发button的服务器端事件;
(2). Button不能有ValidationGroup属性,否则,postback到服务器端,将不会触发button的服务器端事件;

2. 当遇上Validator控件

如果页面上使用了Validator控件,继续使用上面1种的方法,我们会发现,Validator控件失效了。因为将button disable掉后,提交的时候将不再使用Validator控件进行校验。
    针对此问题,一个解决方案,就是提交前手动校验一次。如果我们用IE Develop tool来跟踪提交的JS代码,我们会发现asp.net是在Page_ClientValidate函数中来完成Validator中设置的校验,所以下面手工调用一次该方法,如果校验失败,则不提交:

 <script type="text/javascript">
     function disableButton(button)
     {
         if (typeof (Page_ClientValidate) == ‘function‘ && Page_ClientValidate() == false)
         {
             return false;
         }
         button.disabled = true;
         return true;
     }
 </script>

 <div>
     <asp:TextBox runat="server" ID="tbxInput1"></asp:TextBox>
     <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="tbxInput1"
             ValidationGroup="Group1" ErrorMessage="*"></asp:RequiredFieldValidator>
     <asp:Button runat="server" ID="btnPostBack1" Text="按我1" UseSubmitBehavior="false"
             OnClientClick="disableButton(this);" OnClick="btnPostBack_Click">
         </asp:Button>
 </div>

说明:如果页面上有多个Validator控件,并且多个Button需要进行分组校验,则只需要设置Button的ValidationGroup即可

上面的这个方法,貌似已经完美了;通常情况下,文章写到这里也该结束了,我们的系统也是这么使用的。但是……最近一个客户,老抱怨每个月总有几条重复的业务数据。。。

3. 当用户的点击速度足够快……

根据客户的反馈信息,我们查了下那几条重复的业务数据,发现同样的记录偶尔会出现两次,并且DB中记录的创建时间完全相等(精确到毫秒)。然后也让用户的演示了一下她日常的操作方式,发现她点鼠标相当的快;虽然没有重现问题,但我们也大致知道问题的可能原因了:当用户点击的速度足够快,浏览器还没有来得及将button禁用掉,用户又点击了第二次……

为了重现问题,我们做了如下测试:

 <script type="text/javascript">
         function disableButton(button) //, validateGroup)
         {
             if (typeof (Page_ClientValidate) == ‘function‘ && Page_ClientValidate() == false)
             {
                 return false;
             }
             button.disabled = true;
         }

         function doubleClick()
         {
             var button1 = document.getElementById(‘btnPostBack1‘);
             button1.onclick();
             button1.onclick(); //模拟重复点击2次
         }
     </script>

     <div>
         <asp:TextBox runat="server" ID="tbxInput1"></asp:TextBox>
         <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="tbxInput1"
             ValidationGroup="Group1" ErrorMessage="*"></asp:RequiredFieldValidator>
         <asp:Button runat="server" ID="btnPostBack1" Text="按我1" UseSubmitBehavior="false"
             ValidationGroup="Group1" OnClientClick="disableButton(this);" OnClick="btnPostBack_Click">
         </asp:Button>
     </div>
     <input type="button" onclick="doubleClick();" value="点击一次,模拟连续点击‘按我1‘两次" />

然后页面后台代码如下:

     public static int i = 0;
     protected void btnPostBack_Click(object sender, EventArgs e)
     {
         Response.Write(((Button)sender).Text + "      " + (++i).ToString());//将累加结果输出
     }

每次页面PostBack时,全局变量+1,如果连续PostBack两次,则得到的是+2的累计。测试的结果:除了偶尔+1,大部分情况都是累加2……看来,如果用户点击鼠标的速度足够快,前面2中的办法还是无法杜绝重复提交,咋办呢???

4. 终极绝杀技

处理思路就是,用数组记录用户的点击时间,如果点击时间小于某个时间间隔(下面演示的1秒,即1000毫秒),则认为是重复提交,并取消当前点击事件,直接上代码了:

 <html xmlns="http://www.w3.org/1999/xhtml">
 <head runat="server">
     <script type="text/javascript">
         var date = new Array();
         function disableButton(button, validateGroup)
         {
             date.push(new Date());
             if (date.length > 1
                 && (date[date.length - 1].getTime() - date[date.length - 2].getTime() < 1000))//小于1秒则认为重复提交
             {
                 event.cancelBubble = true; //测试时发现,如果直接单独设置cancelBubble、或者returnValue来取消事件,经常取消不了,依然存在重复提交的可能。因此只好用返回值来实现手工控制!
                 return false;
             }
             if (typeof (Page_ClientValidate) == ‘function‘
                 && ((validateGroup == undefined && Page_ClientValidate() == false)
                         || (validateGroup != undefined && Page_ClientValidate(validateGroup) == false)))
             { //如果指定了ValidateGroup,则只验证改组;如果未指定,则验证全部验证控件
                 return false;
             }

             button.disabled = true;
             return true;
         }

         function doubleClick()
         {
             var button1 = document.getElementById(‘btnPostBack1‘);
             button1.onclick();
             button1.onclick();
         }
     </script>
 </head>
 <body>
     <form id="form" runat="server">
     <div>
         <asp:TextBox runat="server" ID="tbxInput1"></asp:TextBox>
         <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="tbxInput1"
             ValidationGroup="Group1" ErrorMessage="*"></asp:RequiredFieldValidator>
         <asp:Button runat="server" ID="btnPostBack1" Text="按我1" UseSubmitBehavior="false"
             ValidationGroup="Group1" OnClientClick="if(!disableButton(this, ‘Group1‘)) return false;" OnClick="btnPostBack_Click">
         </asp:Button>
     </div>
     <div>
         <asp:TextBox runat="server" ID="tbxInput2"></asp:TextBox>
         <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ControlToValidate="tbxInput2"
             ValidationGroup="Group2" ErrorMessage="*"></asp:RequiredFieldValidator>
         <asp:Button runat="server" ID="btnPostBack2" Text="按我2" UseSubmitBehavior="false"
             OnClientClick="if(!disableButton(this)) return false;" OnClick="btnPostBack_Click">
         </asp:Button>
     </div>
     <input type="button" onclick="doubleClick();" value="点击一次,模拟连续点击‘按我1‘两次" />
     </form>
 </body>
 </html>

说明:
(1). 测试时发现,如果直接单独设置cancelBubble、或者returnValue来取消事件,经常取消不了,依然存在高频率的重复提交。因此只好用返回值来实现手工控制;
(2). disableButton接收一个validateGroup参数,如果指定了ValidateGroup,则只验证改组;如果未指定,则验证全部验证控件。

原文地址:https://www.cnblogs.com/cn2018/p/10132558.html

时间: 2024-10-23 09:28:26

按钮重复点击解决方案的相关文章

github项目解析(七)--&gt;防止按钮重复点击

转载请标明出处:一片枫叶的专栏 本文中我将介绍一下我自己封装的一个小的工具类库:按钮点击事件类库. 作用: 该类库可以防止按钮重复点击,可以判断网络状态,可以判断用户登录状态,以及自定义验证条件等等. 说明: 其实现的核心原理就是通过自定义实现自身的OnClickListener类,并重写其中的onClick方法,在onClick方法中执行相应的判断逻辑之后回调我们自定义的抽象方法. 具体效果如下图所示: 使用方式 屏蔽多次点击事件 /** * 测试快速点击事件 */ fastButton.se

关于javascript中限定时间内防止按钮重复点击的思路

前面的话 有一天心血来潮,1分钟内重复点击了多次博客园首页的刷新博文列表的刷新按钮.果不其然,ip当时就被禁用了.后来,重启自己的路由器,重新获取ip才可以访问博客园主页.那么,设置一个限定时间内(比如1秒)防止按钮被重复点击的方法会不会更好一点呢? 思路一 最直接的思路可能就是点击按钮后,按钮的事件绑定函数解绑,1s后重新绑定函数 <button id="btn">0</button> <script> btn.onclick = function

React Native(十一)&mdash;&mdash;按钮重复点击事件的处理

最初开始做后台管理系统的时候,就曾遇到过这样一种场景:"快速点击确认按钮,就会对此触发确认事件,导致多次请求数据库":于是最终我们得当的通过处理那个确认button,解决了上述问题.而当自己开始使用RN做APP的时候,同样的问题居然也出现了,于是在处理完其他问题后,专门上网搜了一下此类问题的解决办法(不过好像都挺"高深一点",而自己却总认为越简单越好,那就摒弃了网上搜到的办法,另辟蹊径咯).突然意识到或许应该从源头解决,于是在官网中看到了这个: 原来在手机开发中也可

按钮重复点击问题 UIbutton

.h p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c91b13 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; min-height: 21.0px } p.p4 { margin: 0.0px 0.0px 0

小程序 节流函数 (防止按钮重复点击)

function throttle(fn, gapTime) { if (gapTime == null || gapTime == undefined) { gapTime = 1500 } let _lastTime = null // 返回新的函数 return function () { let _nowTime = + new Date() if (_nowTime - _lastTime > gapTime || !_lastTime) { fn.apply(this, argume

谈谈防止重复点击提交&lt;转&gt;

http://www.cnblogs.com/jinguangguo/archive/2013/05/20/3086925.html 首先说说防止重复点击提交是什么意思. 我们在访问有的网站,输入表单完成以后,单击提交按钮进行提交以后,提交按钮就会变为灰色,用户不能再单击第二次,直到重新加载页面或者跳转.这样,可以一定程度上防止用户重复提交导致应用程序上逻辑错误. 不妨引深来看,它不一定发生在表单的提交事件上,同样可以发生在ajax的异步请求上.有效地在web客户端采用一定机制去防止重复点击提交

iOS之防止用户重复点击Button(按钮)问题

在项目中,我们往往会遇到这样的问题:因为网络较慢的原因,用户会不耐烦的一直去点击按钮,这样导致的结果时:相关代码一遍一遍的被重复执行,如果按钮的事件是网络请求的话,这样又导致一种网络请求的循环.所以我们解决的方法是在执行按钮点击事件时,为Button加上防止重复点击的方法. 具体的有以下几种方法: 1.使用performSelector方法 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Menlo; color: #bdb2a0 } s

重复点击主界面(TabBar)按钮刷新界面--点击状态栏回到顶部

1.监听按钮点击 2.判断是否是点击的同一个按钮(记录上次点击的按钮) 3.当重复点击相同按钮时,需要获取当前按钮对应控制器刷新界面 3.1 判断是否重复点击按钮,代码写在哪里? 点击标题按钮,属于精华控制器的事情,所以找到精华控制器.写在点击按钮方法里面 3.2怎么拿到按钮对应的控制器? 通过当前按钮的tag值,从精华控制器的子控制器数组中去 3.3怎么让对应的控制器刷新界面? 在对应的控制器里面提供刷新方法,这样每个控制器都要写,太麻烦 之前我们抽取了父类,只需要在父类中提供一个刷新界面方法

ASP.NET怎么防止多次点击提交按钮重复提交

今天做一个系统,由于服务器有点慢,所以常会被点击两次或三次,提交的数据就是多次了.所以要让按钮点击后,不能再次点击. 对于一个按钮,要让变成恢色的,只要this.disabled=true就可以了,可是在.NET里,添加了ONCLICK后,就无法提交信息了.所以要加上以下代码. <asp:Button ID="btnSub" runat="server" Text="回复" OnClick="btnSub_Click"