如何避免2个jQuery“表单提交”脚本之间的冲突?

时间:2016-06-03 15:58:03

标签: javascript jquery ajax forms

我想要实现的是跟踪表单提交。 但是由于我们用于提交按钮的许多变化,我想要更改当前的代码:

$(document).on('click','input[type="submit"], button[type="submit"]',function(){

通用的东西。我认为最好的方法是$("form") - 注释。

问题是,例如,如果form上有一个ajax脚本,它会被我的additional脚本代码阻止。 基本上我想要实现的是拥有两个世界。

所以第一个是网站目前所拥有的(不是每个网站都有):

$("form").submit(function () {
  // ....do something, maybe ajax submit of the form.....
});

以及我要添加的附加,而不修改网站上已有的任何当前脚本:

$("form").submit(function () {
    $.getJSON("....");
});

我的解决方案应该是第二个脚本(附加)不会干扰任何其他表单脚本。

AN IDEA

使用jQuery addClass向当前页面的表单添加类。

这是什么解决方案?

5 个答案:

答案 0 :(得分:2)

我创建了一个小小的代码片段来演示这个问题:



$(document).ready(function() {

  // Registering form-submission as the first would be a possibility
  $('form').on('submit', function(e) {
    console.log(e.target);
    console.info('My first callback is executing');

    // Do some stuff here, but don't mess with the event-object 
    // (like preventing default or stopping the event-chain)
  });

  // Then afterwards everything else that *might* catch the event
  $('form').on('submit', function(e) {
    console.log(e.target);
    console.info('My second callback is executing');

    // Usually some Ajax-Handler-Callback, that handles sending the form,
    // will preventDefault() and stopImmediatePropagation() - that is why 
    // your general first listener must be registered before any of these callbacks

    console.warn('Second callback stops the event from bubbling/propagating');
    e.stopImmediatePropagation();
    e.preventDefault();
  });

  // This will never happen
  $('form').on('submit', function(e) {
    console.log(e.target);
    console.info('My third callback will never execute');
  });
  
  // Using a delegated event-listener with `useCapture` lets this execute first
  document.addEventListener('submit', function(e) {
    console.info('Capturing the event natively');
  }, true);

});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h1>My Website with a multi-handled form</h1>

<form class="" action="" method="post">
  <input type="text" name="test" value="">
  <button type="submit" name="button">Send</button>
</form>
&#13;
&#13;
&#13;

提交表单时输出代码段:

  

本地捕获事件

<form class action method="post">…</form>
     

我的第一个回调正在执行

<form class action method="post">…</form>
     

我的第二个回调是执行
  第二次回调会阻止事件冒泡/传播

刚刚发生了什么?

按下提交按钮,我们的表单会发出 submit -event。浏览器以指定的event-order中的事件传播开始。事件传播分为两个阶段:event-capturing and event-bubbling

现在我们的首次调用事件监听器是 useCapture -directive。 这是在事件传播捕获阶段期间。

MDN获取 useCapture 的说明:

  

capture:一个布尔值,表示此类型的事件将是   在被派遣到任何人之前派遣到注册的听众   DOM树下面的EventTarget。

完成后,浏览器将以事件传播冒泡阶段开始。

这是所有$('element').on()element.addEventListener()(没有 useCapture 选项)注册的侦听器按其显示顺序调用的地方。

在此阶段,我们的第二个监听器不仅要防止默认(不以标准方式提交表单),还要通过调用e.stopImmediatePropagation()来停止事件传播。

之后事件链/事件传播立即停止。

这就是为什么我们的第三个听众永远不会执行。

  

旁注:使用jQuery并退出事件回调时   return false,jQuery将执行e.preventDefault()和   自动e.stopPropagation()

     

请参阅:http://api.jquery.com/on/

结论

您的场景基本上有两种可能性:

  1. 在其他任何事情之前注册您的默认常规事件监听器(在Snippet中首次注册事件)。

  2. 在捕获阶段注册一个事件监听器,捕获事件并处理来自bubbling-phase get的其他监听器之前的事情(片段中的最后一次事件注册)。

  3. 使用这两种方法,您应该能够在不干扰其他事件监听器的情况下完成任务。

答案 1 :(得分:1)

使用此:

    $(document).on("submit", "form", function (e){

完整示例:

    <form id="form1"><input type="text" /><input type="submit" /></form>
    <form id="form2"><input type="text" /><input type="submit" /></form>

JS:

    $(document).on("submit", "form", function (e) {
      var oForm = $(this);
      var formId = oForm.attr("id");
      var firstValue = oForm.find("input").first().val();
      alert("Form '" + formId + " is being submitted, value of first input is: " + firstValue);
      return false;
     })

     [JS fiddle]: http://jsfiddle.net/pZ3Jn/

答案 2 :(得分:0)

  

我想要实现的是跟踪表单提交。

为什么不使用$(document).on('submit', 'form', function(){});

无论如何提交,都会在每个表单提交时触发。

$(document).ready(function() {

  // Some already existing event handler
  $('#bir').on('submit', function(e) {
    console.log($(this).attr('id'));
    e.preventDefault();
  });

  // Your universal form event handler
  $(document).on('submit', 'form', function(e) {
    console.log('Additional functionality for: ' + $(this).attr('id'));
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form id="bir">
  <input type="submit" />
</form>

<form id="ikki">
  <input type="submit" />
</form>

答案 3 :(得分:0)

之前我曾遇到过这个问题几次,我的解决方案是捕获所有表单节点并将它们与特殊操作相关联。这可能不实用,但也是一种可能的解决方案。

示例

//Getting all form elements 

var formNodes = document.getElementsByTagName('form');

//loop through nodelist and add submit event and special class to each. 

for(var i = 0; i < formNodes.length; i++){

  formNodes[i].addEventListener('submit'  , registerAction)
  formNodes[i].className += "form-" + i;
}


/*This function captures the submitted form and determines 
the action to carry out based off class name .
e.preventDefault will stop page from reloading in case of
making ajax requests.
*/

function registerAction(e){
  e.preventDefault();

  var formTarget = $(e.target).attr('class');

 switch(formTarget){

   case "form-0" :
     // Do something ...

     break;
   case "form-1" :
     // Do something else...
     break;

   default:
     break;


 }

  return false;
}

请记住,registerAction中的逻辑可以根据您的需要进行更改 在这种情况下,我使用了“案例陈述”,因为我觉得它最有意义。

这不完美,但我希望它能给你一个想法......

答案 4 :(得分:0)

  

问题在于,例如,如果表单上有一个ajax脚本,那么   被我的附加脚本代码阻止。

不,它没有。您可以在一个元素上绑定多个处理程序。

对于极少数情况,请参阅其他建议,但如果我说得对,那么您的基本假设是绑定元素上的处理程序取消前一个。嗯,它没有。