如何防止用户单击按钮两次?

Posted

技术标签:

【中文标题】如何防止用户单击按钮两次?【英文标题】:How do I prevent users clicking a button twice? 【发布时间】:2011-09-02 11:46:25 【问题描述】:

我有一个旧的 ASP.NET Web 表单应用程序 (.NET 2.0),当单击按钮时,它的运行过程需要 30 秒左右。我需要防止按钮被点击两次。这将防止发布两次,这会导致数据库中的重复数据。

我尝试添加;

OnClientClick="this.disabled='true';"

尝试禁用 javascript 中的按钮。但是,虽然按钮被禁用,但按钮的回发也不起作用。

禁用按钮以防止多次提交是此应用程序的理想选择。我该怎么做?

编辑

我无法使用第三方控件。

【问题讨论】:

可能重复:***.com/questions/4344408/… 【参考方案1】:

必须在 OnClientClick 之后返回 true:

OnClientClick="this.disabled='true';return true;"

如果要继续回发,客户端中的任何点击都必须返回 true,这是一种在按钮按下时提供客户端验证的方法。

【讨论】:

那行不通。该按钮被禁用,但该按钮不会导致回发。 @Richard 你试过了吗?和你发的不一样 上面没有明确说明,但我想如果它对任何人有帮助,我会添加,这可能是 OP 遇到问题的原因。如果您在单击提交按钮后禁用它,那么它不会回发。 如果提交按钮被禁用,因为 ASP.NET 不会回发,所以它不工作,这也没有考虑页面上的任何验证【参考方案2】:

您可以做的一件事是单击它后将其隐藏在客户端并显示一些加载器图像。

或者如果它是一个表格或其他东西,你可以添加recaptcha

【讨论】:

【参考方案3】:

您还需要set the Button's UseSubmitBehavior property to false

Web 浏览器不会在表单的 POST 数据中包含禁用的元素,即使该元素恰好是最初触发表单提交的按钮。不幸的是,ASP.NET WebForms 的单表单页面设计依赖于这些信息来了解哪个控件引发了 PostBack 以及要执行哪个事件处理程序(即 Button1.On_Click)。

切换到 UseSubmitBehavior="false" 会在客户端 onclick 处理程序中注入 __doPostBack('Button1', '') 以解决该问题。然后,即使您禁用 Button,__doPostBack 参数也会让 ASP.NET 知道哪个控件引发了 PostBack 以及在服务器端触发哪些事件。

【讨论】:

我同意。请参阅下面的***.com/a/11832053/8479,了解执行此操作并使用客户端验证的示例。【参考方案4】:

如果您只是禁用该按钮,那么 ASP.NET 将不会发布该表单。您还想处理客户端验证。这是我的解决方案:

<asp:Button runat="server" ID="btnSave" 
   Text="Save" OnClick="btnSave_Click" 
   OnClientClick="if (!Page_ClientValidate()) return false;  this.disabled = true; this.value = 'Saving...';" 
   UseSubmitBehavior="false" />

有关 UseSubmitBehavior 的说明,请参阅 @Dave Ward's post。

如果您有多个验证组,则需要为此增强此解决方案。

【讨论】:

非常感谢,来自另一篇文章的调整(我现在找不到)对我有用: OnClientClick=" if (Page_IsValid) this.value='Saving...';this .disabled=true; " 删除这部分 if (!Page_ClientValidate()) return false; 为我修复了您的解决方案。 .net 4.5.2 默认网络表单应用程序。 技术上你只需要'this.disabled=true;'。其他都是可选的 如果在 OnClientClick 中使用 javascript 函数 将不起作用? 好东西谢谢你,因为正则表达式验证器而禁用按钮时遇到问题。【参考方案5】:

这是一个快速的解决方案。当他们点击它时,将宽度设置为 0。它仍然会提交,但他们将无法再次单击它。如果您想在出现验证错误的情况下再次显示它,则可以在服务器端单击事件中将 Width 设置回原来的值。

OnClientClick="this.width=0;"

【讨论】:

这个页面有很多比这个更好的解决方案,不会推荐给任何人【参考方案6】:

搜索了一段时间后,我想出了这个解决方案。

$('form').submit(function () 
    $('input[type=submit][data-loading]').addClass('disabled');

    if ($(this).data('submitted') == true) 
        $('input[type=submit][data-loading]').attr('disabled', 'disabled');
        return false;
    

    $(this).data('submitted', true);
);

UseDefaultBehavior 解决方案的问题是 Enter 键停止不提交使用很多的表单。我假设相当一部分用户尝试输入而不是点击。

【讨论】:

【参考方案7】:

我通常将此方法添加到我的 BasePage 以供重复使用。

这段代码也处理验证

/// <summary>
///  Avoid multiple submit
/// </summary>
/// <param name="button">The button.</param>
/// <param name="text">text displayed on button</param>
public void AvoidMultipleSubmit(Button button,string text="wait..." )

    Page.ClientScript.RegisterOnSubmitStatement(GetType(), "ServerForm", "if(this.submitted) return false; this.submitted = true;");
    button.Attributes.Add("onclick", string.Format("if(typeof(Page_ClientValidate)=='function' && !Page_ClientValidate())return true;this.value='1';this.disabled=true;0",
        ClientScript.GetPostBackEventReference(button, string.Empty),text));

【讨论】:

两个建议。首先 - 使参数 WebControl 不是 Button。其次,与“功能”相比,使用“===”。【参考方案8】:

我发现这个链接对解决这个问题非常有用 Disable ASP.Net button after click to prevent double clicking

希望能帮到你:)

【讨论】:

我现在使用 onbeforeunload 来避免 close Window Browser , Alt + F4, F5 和我控制 回传。如何在这两种情况下使用它 onbeforeunload【参考方案9】:

优势

开箱即用,适用于所有按钮 即使没有触发提交的按钮也会被禁用。 链接按钮也将被禁用。 适用于 UpdatePanel(即部分和异步回发) 适用于完整回发 验证阻止回发时不会禁用按钮 按钮按下、回车键按下和 AutoPostBack 事件将导致按钮被禁用

限制

† 我见过的大多数其他解决方案都有同样的限制

依赖 jQuery 仅适用于 ASP 表单 如果用户在提交后点击浏览器的取消按钮,用户将无法再次提交,可能会感到困惑。 用户可以通过其他方式发起回发: 使用回车键提交 自动回发事件

代码

只需将此 sn-p 放在 html 代码底部的 &lt;/body&gt; 结束标记之前。

<script type="text/javascript">
    jQuery(function ($) 

        /*
         * Prevent Double Submit
         * ---------------------
         * Disables submit buttons during form submission and asp async postbacks
         */

        // class name assigned to disabled :submit elements
        var disabledClass = 'asp-postback-disable';

        // selector for buttons and other elements that may cause a postback
        var submittableSelector = [
            'a[href^="javascript:__doPostBack"]',
            ':submit'
        ].join(",");

        // returns false; used to prevent event bubbling
        function returnFalse()  return false; 

        // logs errors
        function error(ex) 
            if (typeof console === 'object' && console.error != null) 
                console.error('Prevent Double Submit Error:', ex);
            
        

        // disables :submit elements
        function disableSubmit() 
            try 
                $(submittableSelector, 'form')
                    .addClass(disabledClass)
                    .on('click.asp-postback-disable', returnFalse);
            
            catch (ex)  error(ex); 
        

        // enables :submit elements
        function enableSubmit() 
            try 
                $('.asp-postback-disable,' + submittableSelector, 'form')
                    .removeClass(disabledClass)
                    .off('click.asp-postback-disable', returnFalse);
            
            catch (ex)  error(ex); 
        

        // Handle async postbacks
        if (typeof Sys === 'object') 
            var prm = Sys.WebForms.PageRequestManager.getInstance();
            prm.add_beginRequest(function (s, e)  disableSubmit(); );
            prm.add_endRequest(function (s, e)  enableSubmit(); );
        
        else 
            error('Sys is undefined.');
        

        // Handle navigation (eg, Full postback)
        $(window).bind('beforeunload', function (e) 
            disableSubmit();
        );

    );
</script>

<style type="text/css">
    .asp-postback-disable  opacity: 0.25; 
</style>

【讨论】:

【参考方案10】:

为了规避所有验证和验证组问题,我发现使用window.onbeforeunload 事件最简单,就像这样

<script type = "text/javascript">
function DisableButton() 
    document.getElementById("<%=Button1.ClientID %>").disabled = true;

window.onbeforeunload = DisableButton;
</script>

一旦页面准备好执行包括验证在内的回发或提交 ASP.Net 表单,上述脚本就会禁用 ASP.Net 按钮。

Disable ASP.Net button after click to prevent double clicking

【讨论】:

这可以解决问题。当我尝试实施时,上述解决方案是有问题的。此解决方案的唯一缺点是它会立即禁用按钮,它会在卸载之前按上述方式执行,因此如果代码花费太长时间,用户可能会单击两次 我不能排除这种可能性,但我只是做了一些简单的测试,但似乎按钮在我释放鼠标按钮的那一刻被禁用,没有明显的延迟。我无法再次单击它(也已通过 Chrome 开发人员工具验证)。我的手指慢了一个数量级。我很想知道是否有人设法击败 onbeforeunload ;) 我同意,在大多数情况下它会非常快。但是,可能存在 OnUserClick= 在提交之前执行延长脚本的情况。【参考方案11】:

您还可以隐藏按钮或将其更改为加载 gif 以保持反馈

$(document).on('submit','form',function (e) 
    $("input.SubmitButton").hide();
    // or change if to an loading gif image.
    return true;
);

【讨论】:

【参考方案12】:

上面提供的大多数建议禁用的解决方案都不起作用,因为您不会收到 PostBack。这是我见过的最简单、最干净的解决方案:

OnClientClick="if(this.value === 'Saving...')  return false;  else  this.value = 'Saving...'; "

【讨论】:

这应该是真正的答案。您可以做的另一项改进是添加一个 setTimeout,它将文本更改回原始文本。 var tempText=this.value; this.value='正在保存...'; setTimeout(function ()this.value=tempText;,4000);【参考方案13】:

从 aspx.cs 文件中,您可以添加脚本来解决这个问题(这是唯一对我有用的解决方案,由 wexxix 提供)

//Declaring the string to hold the script
string doubleClickScript = @"<script type='text/javascript'>
                                    function DisableButton() 
                                    document.getElementById('YOURBUTTONID').disabled = true;
                                
                                window.onbeforeunload = DisableButton;
                                </script>";
//Injecting the script to the aspx page.        
ClientScript.RegisterStartupScript(this.GetType(), "DoubleClickScript", doubleClickScript);

显然,您可以将脚本添加到页面中,我只是这样使用,因为我刚刚可以访问客户的 C# 代码。 谢谢

【讨论】:

【参考方案14】:

您也可以通过创建具有相同样式的客户端按钮、隐藏“原始”服务器端按钮并使用 javascript 禁用 HTML 按钮/调用原始按钮进行点击来“破解”它。

在下一次回发中,它会自动恢复您对客户端按钮的更改 :)。

<asp:Button ID="btnSubmitQuote" class="btn btn-red btn-block" runat="server" Text="Submit Quote" style="display:none;" OnClick="btnSubmitQuote_Click" UseSubmitBehavior="false" />

<button id="btnSubmitQuoteClient"  class="btn btn-red btn-block" onclick ="disableBtn(this);">Submit Quote</button>
<script type="text/javascript">
 function disableBtn(t) 
    t.setAttribute('disabled', 'disabled');
    var btn = document.getElementById('<%=btnSubmitQuote.ClientID %>');
    btn.click();
  

【讨论】:

【参考方案15】:

在表单的 Page_Load 事件中输入这一行:

btnSubmit.Attributes.Add("onclick", " this.disabled = true; " + ClientScript.GetPostBackEventReference(btnSubmit, null) + ";");

来源:dotnetodyssey.com

【讨论】:

以上是关于如何防止用户单击按钮两次?的主要内容,如果未能解决你的问题,请参考以下文章

如何在运行时阻止forEach循环不执行两次?

如何防止活动在按下按钮时加载两次

如何避免重复请求按钮单击两次

java - 如何在java脚本或jquery中单击两次相同的按钮时计算间隔时间

由于文本框失去焦点,按钮需要单击两次

Kotlin:片段内的按钮需要在开始活动之前单击两次。如何一键启动活动?