jQuery AJAX表单提交两次

53
我有一个表单,通过jQuery捕获并通过AJAX发送。我的问题是每次刷新页面时表单会提交多次。我尝试取消绑定提交按钮,但是第一次提交后表单会正常提交。希望能得到帮助。
$('#exportForm').submit(function() {
  $.ajax({
    type: "POST",
    url: $(this).attr('action'),
    data: $(this).serialize(),
    success: function(response) {
      $('#exportForm').unbind('submit');
      console.log(response);
    }
  });
  return false;
});

1
我认为你需要提供更多的代码。 - vborutenko
3
嘿,宠儿,除了一个非常基本的表格之外,那就没什么了。你还需要什么? - James Privett
10个回答

129

在调用preventDefault的同时,也要在事件上调用stopImmediatePropagation

$('#exportForm').submit(function(e){
    e.preventDefault();
    e.stopImmediatePropagation();
    $.ajax({
        type: "POST",
        url: $(this).attr( 'action' ),
        data: $(this).serialize(),
        success: function( response ) {
            console.log( response );
        }
    });

    return false;
});

16
虽然您的回答可能解决了问题,但如果您能提供有关如何解决问题的说明,那将会更好。在这种情况下,为什么“preventDefault”不足够。这是对进一步改善此次和未来回答的建议。 - Luís Cruz
15
加入 e.stopImmediatePropagation(); 对我很有帮助,谢谢 Chris!今晚我已经为此苦思冥想了大约2个小时。虽然我以前仅使用 e.preventDefault() 也可以达到效果,但我怀疑这是因为它适用于简单的链接或按钮,但在处理表单提交事件时,必须使用 e.stopImmediatePropagation() 来防止事件通过 dom 冒泡。请参见 http://api.jquery.com/event.stopImmediatePropagation/。 - Robini
1
你说得没错,但这对我也不起作用,可能的原因是什么? - Veshraj Joshi
return false;足以防止默认行为和事件冒泡。 - mingca

36

你最有可能是使用 button 或者 submit 来触发ajax事件。尝试这样:

$('#exportForm').submit(function(e){
        e.preventDefault();
        $.ajax({
            type: "POST",
            url: $(this).attr( 'action' ),
            data: $(this).serialize(),
            success: function( response ) {
                console.log( response );
            }
        });

        return false;
    });

谢谢,我移除了 "$('#exportForm').unbind('submit');" 并添加了 "e.preventDefault();",看起来它已经起作用了。我会在可以的时候接受它。 - James Privett
有趣 - 你是说 return false 不能阻止默认的表单提交操作?http://jsfiddle.net/rR8Xz/ - wirey00
2
抱歉,经过更多的测试发现它不起作用。 - James Privett
3
什么不起作用?它仍然提交两次吗?你应该明白,所有这些AJAX例程所做的只是通过POST进行相当标准的提交。如果#exportForm是一个按钮,我建议你将.submit更改为.click - DevlshOne
2
这对我也没用,我不得不像Chris Sercombe在下面建议的那样添加e.stopImmediatePropagation();。 - Robini

11

如果您使用某种验证方式(例如jQuery验证),则表单将被提交两次,因为除了您自己编写的$('#exportForm').submit外,验证插件还会在成功验证所有字段后提交表单。

NB:如果您使用jQuery验证,请避免使用.submit()。相反,请使用submitHandler


7
您可以简单地使用e.stopImmediatePropagation();
例如:
$('#exportForm').submit(function(e){
    e.stopImmediatePropagation();

2
正如Chris Sercombe指出的那样,e.stopImmediatePropagation()确实起作用并且可以解决问题,但你不应该使用它。问题仍然存在于你的代码中的某个地方。让我举一个例子来说明如何发送两个post请求:
如果你正在使用AngularJS,并且假设你创建了一个名为“HandleAjaxController”的控制器,你可以将这个ng-controller分配给一个div,然后意外地将这个相同的ng-controller分配给内部的div。这将导致post请求被发送两次。所以:
    <div ng-controller='HandleAjaxController'>
        <div ng-controller='HandleAjaxController'>
            <button id="home" type="button" class="btn btn-success">Send data</button>

这曾经给我带来了很大的压力,因为在我的ng-route中,我设置了控制器如下:
    $routeProvider
    .when("/", {
        templateUrl : "src/js/partials/home.html",
        controller : "HandleAjaxController"
    })

然后我在home.html中重新设置了它:<div ng-controller='HandleAjaxController'>

无论如何,这是两个帖子可以被发送的一个例子。


1
你应该检查一下另一个js代码,可能某处触发了两次“submit”事件。在我的情况中就是这样,我忘记在一个按钮的onclick处理程序中添加“return false”。

0
对于那些遇到几乎相同问题的人,我可以说你应该将jQuery事件控制在function(){}之外,这样最好的方法是像这样使用事件来进行ajax POST请求:
$(document).ready(function {
 $("#exportForm").click(function{
   $.ajax({
      type: "POST",
      url: "#", //your url
      data: data, //your variable
      success: function(){
        //do something here
      }
   });
 });
});

不在调用第二个函数的函数中,像这样:

$(document).ready(function {
 exportingForm();

 function exportingForm(){
   $("#exportForm").click(function{
     $.ajax({
        type: "POST",
        url: "#", //your url
        data: data, //your variable
        success: function(){
          //do something here
        }
     });
   });
 }
});

0

我想指出,如果您有多个具有相同类的元素,这也可能发生。

<button class="downvote">
  <img src="/img/thumbs-down.png" class="downvote">
</button>

0

-3
问题可以通过在您的PHP表单中使用div代替按钮来解决。由于使用了ajax,因此不需要按钮。

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