防止在jQuery中双重提交表单

Ada*_*dam 164 javascript forms jquery http-post double-submit-prevention

我有一个表单,需要一段时间服务器来处理.我需要确保用户等待并且不再尝试通过再次单击该按钮重新提交表单.我尝试使用以下jQuery代码:

<script type="text/javascript">
$(document).ready(function() {
    $("form#my_form").submit(function() {
        $('input').attr('disabled', 'disabled');
        $('a').attr('disabled', 'disabled');
        return true;
    });
});
</script>
Run Code Online (Sandbox Code Playgroud)

当我在Firefox中尝试此操作时,所有内容都被禁用,但表单未提交任何它应包含的POST数据.我不能使用jQuery提交表单,因为我需要使用表单提交按钮,因为有多个提交按钮,我确定哪个用于POST中包含哪个值.我需要像往常一样提交表单,我需要在发生后立即禁用所有内容.

谢谢!

Nat*_*ong 310

2018年的更新:我刚刚得到了一些旧的答案,并且只是想补充一点,最好的解决方案是使操作具有幂等性,以便重复提交是无害的.

例如,如果表单创建订单,请在表单中添加唯一ID.服务器第一次看到具有该ID的订单创建请求时,它应该创建它并响应"成功".随后的提交也应该响应"成功"(如果客户没有得到第一个响应)但不应该改变任何东西.

应通过数据库中的唯一性检查来检测重复项,以防止竞争条件.


我认为你的问题是这一行:

$('input').attr('disabled','disabled');
Run Code Online (Sandbox Code Playgroud)

您正在禁用所有输入,包括,我猜,表单应该提交的数据.

要仅禁用提交按钮,您可以执行以下操作:

$('button[type=submit], input[type=submit]').prop('disabled',true);
Run Code Online (Sandbox Code Playgroud)

但是,即使这些按钮被禁用,我也不认为IE会提交表单.我建议采用不同的方法.

一个jQuery插件来解决它

我们刚刚使用以下代码解决了这个问题.这里的诀窍是使用jQuery data()将表单标记为已提交或未提交.这样,我们就不必弄乱提交按钮,这会让IE出局.

// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
  $(this).on('submit',function(e){
    var $form = $(this);

    if ($form.data('submitted') === true) {
      // Previously submitted - don't submit again
      e.preventDefault();
    } else {
      // Mark it so that the next submit can be ignored
      $form.data('submitted', true);
    }
  });

  // Keep chainability
  return this;
};
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

$('form').preventDoubleSubmission();
Run Code Online (Sandbox Code Playgroud)

如果有一些AJAX表单应该被允许每页加载多次提交,你可以给它们一个表示它的类,然后将它们从你的选择器中排除,如下所示:

$('form:not(.js-allow-double-submission)').preventDoubleSubmission();
Run Code Online (Sandbox Code Playgroud)

  • 当使用jquery验证不显眼的验证时,更好地检查表单是否有效.if($(this).valid)){$ form.data('submitted',true);} (21认同)
  • @Stuart.Sklinar - 好主意.我使用`$ form`虽然 - 'form'因为它更具描述性,而领先的`$`因为我的约定,这意味着它是一个jQuery对象. (5认同)
  • 只是一个指针 - 将`$(this)`缓存到`var = $(this)`不是更好吗? (2认同)

Ctr*_*l-C 43

时机方法是错误的 - 您如何知道该操作将在客户端的浏览器上花多长时间?

怎么做

$('form').submit(function(){
  $(this).find(':submit').attr('disabled','disabled');
});
Run Code Online (Sandbox Code Playgroud)

提交表单时,它将禁用内部的所有提交按钮.

请记住,在Firefox中禁用按钮时,当您返回历史记录时,将记住此状态.例如,要防止必须在页面加载时启用按钮.

  • 使用这种方法要非常小心,如果您在提交按钮上有一个值并且您需要它,则表单将不会提交它。 (3认同)
  • +1因为firefox提示,除了在页面加载时启用按钮还有其他选项吗? (2认同)

PTK*_*PTK 19

我认为Nathan Long的答案是要走的路.对我来说,我正在使用客户端验证,所以我只是添加了一个表单有效的条件.

编辑:如果没有添加,如果客户端验证遇到错误,用户将永远无法提交表单.

        // jQuery plugin to prevent double submission of forms
        jQuery.fn.preventDoubleSubmission = function () {
            $(this).on('submit', function (e) {
                var $form = $(this);

                if ($form.data('submitted') === true) {
                    // Previously submitted - don't submit again
                    alert('Form already submitted. Please wait.');
                    e.preventDefault();
                } else {
                    // Mark it so that the next submit can be ignored
                    // ADDED requirement that form be valid
                    if($form.valid()) {
                        $form.data('submitted', true);
                    }
                }
            });

            // Keep chainability
            return this;
        };
Run Code Online (Sandbox Code Playgroud)


Rob*_*rty 9

event.timeStamp在Firefox中不起作用.返回false是非标准的,你应该打电话event.preventDefault().虽然我们正在使用它,但总是使用带有控件构造的大括号.

总结以前的所有答案,这里有一个插件,可以完成工作并跨浏览器工作.

jQuery.fn.preventDoubleSubmission = function() {

    var last_clicked, time_since_clicked;

    jQuery(this).bind('submit', function(event) {

        if(last_clicked) {
            time_since_clicked = jQuery.now() - last_clicked;
        }

        last_clicked = jQuery.now();

        if(time_since_clicked < 2000) {
            // Blocking form submit because it was too soon after the last submit.
            event.preventDefault();
        }

        return true;
    });
};
Run Code Online (Sandbox Code Playgroud)

为了解决Kern3l,计时方法对我来说很简单,因为我们试图停止双击提交按钮.如果您对提交的响应时间很长,我建议您使用微调器替换提交按钮或表单.

完全阻止表单的后续提交,如上面的大多数示例所做的那样,有一个不好的副作用:如果网络出现故障并且他们想要尝试重新提交,他们将无法这样做并且会丢失更改制作.这肯定会让一个愤怒的用户.

  • 你是对的.你可以反过来 - 立即禁用,然后,在一些长时间超时后,再次启用.防止双击,允许重新提交,但仍允许滞后用户无效重新提交. (2认同)

Max*_*kov 8

请查看jquery-safeform插件.

用法示例:

$('.safeform').safeform({
    timeout: 5000,  // disable next submission for 5 sec
    submit: function() {
        // You can put validation and ajax stuff here...

        // When done no need to wait for timeout, re-enable the form ASAP
        $(this).safeform('complete');
        return false;
    }
});
Run Code Online (Sandbox Code Playgroud)