阻止默认事件方法"event.preventDefault()"在ajax中无效

5

我正在注册表单上触发一个AJAX调用,检查用户输入的电子邮件是否已被使用。 Ajax函数:

<script>


$( "#becomesignup" ).submit(function( event ) {
        $.ajax({
            url : 'login', // Your Servlet mapping or JSP(not suggested)
            data : {"email":$("#becomeemail").val()},
            type : 'GET',
            dataType : 'html', // Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
            success : function(response) {
                if(response == "true"){
                    $('#emailerrorbecome').slideDown();
                    $('#become-submit').prop('disabled', true);
                  event.preventDefault();
                }else{
                    $('#emailerrorbecome').slideUp();
                    $('#become-submit').prop('disabled', false);
                }
                 $('.black-screen').hide();

              },
              error : function(request, textStatus, errorThrown) {
                alert(errorThrown);

            }
        });
});
</script>

在上面的ajax函数中,如果响应为true,则表示该电子邮件已经被使用,我需要显示一个错误div($('#emailerrorbecome').slideUp();)并防止表单提交。但是即使使用event.preventDefault(),也无法阻止注册相同的电子邮件ID。 请帮助我解决这个问题。谢谢。

1
你应该在 $.ajax 之前编写它。事件不是 asyc :D。只有 ajax 可以是 async - Parth Trivedi
7
event.preventDefault(); 应该放在事件处理程序中,而不是放在 AJAX 的 complete/success/error 块中。 - Tushar
4个回答

9

在jq提交处理程序中,您应该以编程方式提交表单并始终防止默认行为。例如,使用上下文并调用submit() DOM API方法:

$("#becomesignup").submit(function(event) {
    event.preventDefault(); /* prevent form submiting here */
    $.ajax({
        context: this, /* setting context for ajax callbacks*/
        url: 'login', // Your Servlet mapping or JSP(not suggested)
        data: {
            "email": $("#becomeemail").val()
        },
        type: 'GET',
        dataType: 'html', // Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
        success: function(response) {
            if (response == "true") {
                $('#emailerrorbecome').slideDown();
                $('#become-submit').prop('disabled', true);  
                $('.black-screen').hide(); /* hide it here */
            } else {
                $('#emailerrorbecome').slideUp();
                $('#become-submit').prop('disabled', false);
                this.submit(); /* 'this' refers to the FORM, and calling submit() DOM native method doesn't fire again jq handler */
            }
        },
        error: function(request, textStatus, errorThrown) {
            alert(errorThrown);

        }
    });
});

如需了解原因why,请参见Quentin的答案


1
@mplungjan:不,A.Wolff是正确的,因为已提供了context:this - iCollect.it Ltd
我喜欢这个,因为它避免了哨兵标志。我一直犹豫是否更改Ajax回调上下文,但我看不到任何缺点+1 :) - iCollect.it Ltd

5
您调用了preventDefault的时间太晚了。
执行顺序如下:
  1. 事件处理程序触发。
  2. 发送HTTP请求。
  3. 事件处理程序完成。
  4. 未调用preventDefault,则默认行为发生。
  5. 接收到HTTP响应。
  6. 成功处理程序触发。
  7. 调用预防默认行为...太晚了,已经没有任何效果了。
您不能等待HTTP响应返回才阻止默认行为。
您需要始终防止默认行为,并在提交处理程序中使用JS有条件地重新提交表单,或将使用Ajax执行测试的逻辑移动到不依赖于表单提交事件的位置,例如,在数据输入完成后立即运行它,并准备好表单可能在您的JS运行完成之前提交的情况。

嗨Quetin,我尝试始终防止默认行为,然后在提交处理程序中使用JS重新提交表单,但当我重新提交表单时,它又回到了$(“#becomesignup”).submit(function(event){}和形成无限循环。我该怎么做才能避免这种情况? - Uday Khatry
2
如果您调用DOM API的submit(),它不会触发jq处理程序。 - A. Wolff
1
@UdayKhatry,你测试过我的答案了吗?我设置上下文,然后使用this.submit();。如果使用$("#becomesignup").submit();,你会不断调用同一个jq处理器,从而导致无限循环… - A. Wolff
@A.Wolff,我也尝试了使用this.submit(); ,但是控制台显示出现错误:"Uncaught TypeError: this.submit is not a function"。 - Uday Khatry
1
@UdayKhatry 我不知道该说什么... 你必须更仔细地阅读我的答案,我清楚地解释了你必须将上下文设置为this作为ajax选项... 如果你只是简单地复制/粘贴答案的某个部分而不试图理解你正在复制/粘贴的内容,我们还能说什么呢?! - A. Wolff
显示剩余3条评论

4

submit 函数返回后,你无法阻止提交。Ajax 结果发生得更晚。

相反,你可以设置一个标识(例如使用哨兵变量),并在不允许的情况下取消提交。然后从 Ajax 回调函数中触发一个 submit 事件。

示例:

var allowSubmit = false;
$( "#becomesignup" ).submit(function( event ) {
    if (!allowSubmit){
        $.ajax({
            url : 'login', // Your Servlet mapping or JSP(not suggested)
            data : {"email":$("#becomeemail").val()},
            type : 'GET',
            dataType : 'html', // Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
            success : function(response) {
                if(response == "true"){
                    $('#emailerrorbecome').slideDown();
                    $('#become-submit').prop('disabled', true);
                  // Enable next submit to proceed
                  allowSubmit = true;
                  // And trigger a submit
                  $( "#becomesignup" ).submit();

                }else{
                    $('#emailerrorbecome').slideUp();
                    $('#become-submit').prop('disabled', false);
                }
                 $('.black-screen').hide();

              },
              error : function(request, textStatus, errorThrown) {
                alert(errorThrown);

            }
        });
    }
    // return false does e.preventDefault(), and true allows it to proceed
    return allowSubmit;
});

注意:@A. Wolff的答案也做了同样的事情,但没有使用哨兵变量,因为它保存了form DOM元素的上下文并调用了本地DOM提交(绕过了jQuery submit)。两种解决方案都可以工作,但我会选择他的解决方案(从现在开始我会这么做) :) - iCollect.it Ltd
$( "#becomesignup" ).submit(); 应该改为 $( "#becomesignup" )[0].submit(); :) 编辑:哦不,我知道你在做什么。 - A. Wolff
@A. Wolff:我的解决方案不是这样的。请检查哨兵标志的使用。在运行jQuery提交之前,它会清除该标志。既然我已经看到了你的方法,我也可以用另一种方式来做,但最好将此答案作为另一种选择留下 :) - iCollect.it Ltd
抱歉,那么你应该调用DOM API方法,并在else语句中执行,或者我漏掉了一些逻辑。 - A. Wolff
@A.Wolff:是的,你漏了什么 :) 它清除标志,然后触发提交,允许其通过下一个提交调用而不阻止默认值(也不再次运行ajax)。你的代码更短/简单,但用户需要理解ajax“上下文”的使用。 - iCollect.it Ltd

0

你可以使用return false代替eventPreventDefault。 我之前一直使用location.reload()作为一种不太优雅的方法来刷新页面以防止提交,但是return false即使没有刷新也能很好地工作,它不会提交表单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接