Chrome/Safari中表单被提交两次

7

我想进行一个基本的表单提交,但是在Chrome和Safari中以下内容会向服务器提交两次(但在Firefox中表现正常):

<form id="create-deck-form" action="/decks/create" method="post">
  <fieldset>
    <legend>Create new deck</legend>
    <label for="deck-name-field">Name</label>
    <input id="deck-name-field" name="deck-name-field" type="text" value="" maxlength="140" />

    <label for="tag-field">Tags</label>
    <input id="tag-field" name="tag-field" type="text" value="" maxlength="140" />

    <input class="add-button" type="submit" value="Create" />
  </fieldset>
</form>

我想使用 onsubmit 属性在提交前对字段进行验证,但无论何时返回值为 true,表单都会被提交两次。
我试图将一个 jQuery 处理程序绑定到表单上,但是如果默认行为没有被阻止,则表单仍然会被提交两次,例如:
<script type="text/javascript">
 $(document).ready(function() {
     $("#create-deck-form").submit(function(event){
          if($("#deck-name-field").val() == "") {
            event.preventDefault();
            alert("deck name required");
          }
        });
 });
</script>

我想,对于一个新手来说,在这里肯定有一些明显的问题,但我深深地困惑为什么在Chrome和Safari中提交(包括验证或不验证)会使服务器上发布重复的帖子。如果您能提供任何见解,我将不胜感激。


1
越想这个问题,它就越奇怪。如果我想让一个表单被提交两次,我不知道该怎么做(除非将表单连接到 AJAX 提交机制)。 - Pointy
@Pointy,我知道表单会被提交两次,因为我可以在开发控制台中看到网址被击中两次,并且当通过Chrome/Safari创建卡组时,我也可以在开发(和现场)应用程序上看到幻影卡组。我的AJAX表格运行得非常好,特别是本周我正在转移到jQuery表格插件,只有这个特定的表格让我很费劲。 - meg
1
@meg,有没有可能页面导入的某些JavaScript文件会将某些内容附加到表单或按钮上?你可以(实验性地)尝试省略一些脚本文件,看看是否有所不同。当然,这并不清楚为什么会导致Chrome和FF之间的不同行为,但这是一个奇怪的问题。 - Pointy
1
@Pointy!我撕掉了所有连接的JS和其他东西,但某个地方正在未经请求的情况下对我的表单进行某些操作!当它开始运行时,我会告诉你的。我只是知道这是某种非常愚蠢的事情 ;) - meg
那是个好消息。难道福尔摩斯没有说过,解开谜团的答案从来不是某些不可能发生的事情吗? :-) - Pointy
显示剩余11条评论
4个回答

3
这个问题实际上与Facebox (http://defunkt.github.com/facebox/)有关。Facebox初始化会在页面加载后引起第二组请求。因此,如果你发布到/myaction/create,Facebox将启动第二组请求,并将基本URL设置为/myaction/create。解决方法是在执行post请求后重定向到处理get请求的URL,这样就不会重复执行post请求了。非常感谢您的帮助。

1
我似乎有同样的问题,你有代码(或全局描述)解决方案吗?你是如何在post之后重定向get的? - michel.iamit

1

我不是100%确定,但请尝试这个:

<script type="text/javascript">
   $(document).ready(function() {
      $("#create-deck-form").submit(function(event){
         if(!$("#deck-name-field").val().length) {
           return false;
         }
       });
   });
</script>

如果那不起作用,请看一下:
for(e in $("#create-deck-form").data('events'))
    alert(e);

这将提醒您所有绑定到您的表单的事件。也许还有更多的事件处理程序?否则也要警报/记录日志

$("#create-deck-form").attr('onclick')

并且

$("#create-deck-form").attr('onsubmit')

以防万一。


是的,我很确定你需要返回false来阻止浏览器默认事件的发生。 - Tom
感谢Andy和Tom。我觉得我可能通过提到验证搞混了问题。如果验证失败,我没问题(event.preventDefault等同于return false,两者都没问题),只有当表单在没有验证问题的情况下提交时才会出现问题。因此,如我在第一个代码片段中所示,基本的表单提交没有验证或JS参与会提交两次到服务器。关于检查与表单相关联的任何流氓处理程序的好主意,Andy,我会试试。 - meg
@meg:不完全正确,从事件处理程序返回“false”会触发preventDefaultstopPropagation两个操作。 - jAndy
@Andy,我可以确认表单上没有绑定任何意外的处理程序。@jAndy,我明白了!非常感谢。不过我不确定这如何帮助解决我的当前问题。在我的情况下,当验证通过时出现了意外行为,因此既没有阻止默认行为的代码也没有返回false。 - meg

0

好的,不确定这会有多大帮助,但尝试删除提交按钮并通过JavaScript提交表单。例如:

<input id="submit-button" class="add-button" type="button" value="Create" />

那么,你可以尝试不再监听onsubmit事件,而是

$('#submit-button').click(function(evt) {
    if(validationSuccess(...)) {
        $("#create-deck-form").submit();
    } else {
        //display whatever
    }
});

现在你的方法也应该可以工作了...但是这种方式可以帮助你调试出问题所在...这应该只提交一次...祝你好运!


谢谢JavaDrinker,我确实尝试过这种方法,但是没有成功。我一直在挖掘问题的深层次原因,希望今天能够解决并发布解决方案。 - meg
这可能是一个愚蠢的问题,但是:你是如何确定你的表单被提交了两次?我的意思是,“双重提交”的结果是什么? - Java Drinker
我可以在我的控制台打印输出中看到有两个请求发送到服务器,并且数据存储中有第二个牌组可见。结果证明这不是表单提交,但那可能是行为被触发的地方 - 红鲱鱼! - meg

0

你可以尝试在警告后加上 return false;,并删除 event.preventDefault();。也许你还需要在 else 子句中加上 return true;。我相信我在某个地方已经实现了这个功能。


谢谢,Koen。当验证失败时,行为是正确的(是的,event.preventDefault();或return false;都按预期执行)。在验证通过的地方,表单会提交两次。这种情况下,默认行为被显式调用(使用else子句返回true)或者未阻止默认行为/返回false(如上面的代码片段中所示)。 - meg
你尝试过使用非匿名方法(定义名称)并将其用作属性吗?例如:<form ... onsubmit="return validationMethod();">。如果这也导致了两次提交,那么问题就在你的代码其他地方了... - Koen
当然,@Koen,谢谢。问题不在于表单提交,而是在哪里开始的奇怪行为。 - meg

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