如何更改同一事件的事件触发顺序?

时间:2012-02-15 23:05:57

标签: javascript jquery events

Jquery绑定是惊人的,但我不知道绑定发生的顺序。我现在的问题是:

$(document.body).delegate('form', methods.checkForm);
$('form').bind('submit', methods.submitFormIfCheckedFormIsTrue);

methods.checkForm = function (e) {
    if (!$(this).isVerified()) {
        return false;
    }
    return true;
};
methods.submitFormIfCheckedFormIsTrue = function (e) {
    e.preventDefault();
    $.ajax("/submitForm", {
        data:$(this).serialize(),
        type:"post"
    });
};

这显然不是我正在使用的实际代码,但它非常接近。会发生什么,commitFormIfCheckedFormIsTrue函数在checkForm函数之前或期间触发,因此检查非常无用。我的黑客是将“已检查”类添加到表单中并检查表单是否在其他函数中具有该类...但是然后单击提交,它会检查,然后您必须再次单击它以提交它如果一切顺利......那是迟钝的。

对于这个问题而言,另一件重要的事情是,由于无法改变的原因,我在应用程序中处于完全不同的部分。而且,它们是异步加载的。

我想知道的主要事情是...如何更改顺序,或以某种方式设置事件的优先级......

2 个答案:

答案 0 :(得分:3)

如果您在示例中使用“委托”,那么ajax提交总是先运行,因此对您的问题的简短回答是“你不能”。您的委托附加到'body'元素,因此附加到DOM树中更靠近表单的元素的事件将首先触发。

来自表单的事件泡沫 - >身体,所以当你这样做时没有排序。

一种选择是让您的验证触发第二次事件。

methods.checkForm = function (e) {
  e.preventDefault()

  if ($(this).isVerified()) {
    $(this).trigger('form-verified');
  }
};

然后,不将其他处理程序绑定到'submit',而是将其绑定到'form-verified'

$('form').bind('form-verified', methods.submitFormIfCheckedFormIsTrue);

如果它们附加到同一个元素而不是使用委托,这也是完成排序事件的另一种方法。

此外,如果您使用的是jQuery> = 1.7,那么您应该使用on而不是binddelegatehttp://api.jquery.com/on/

<强>更新

如果两者都绑定到同一元素,则它们将按照它们附加到元素的顺序触发。假设checkForm绑定在另一个之前,那么问题是return false;如果它们附加到同一元素,则不会阻止其他事件触发。为此,您还需要e.stopImmediatePropagation()

methods.checkForm = function (e) {
  e.preventDefault()

  if (!$(this).isVerified()) {
    e.stopImmediatePropagation();
  }
};

如果你不得不调整事件的顺序,这里也有一个有用的答案。 jQuery event handlers always execute in order they were bound - any way around this?

答案 1 :(得分:0)

在一般意义上,事件处理程序将按它们绑定的顺序调用,但前提是它们绑定在同一级别。在您的情况下,您将一个直接绑定到表单,而另一个是绑定在document.body级别的委托处理程序。直接绑定的将首先发生,然后事件冒泡,由另一个处理。

如果您将两个处理程序与.delegate()绑定在同一级别,则应按顺序调用它们:

$(document.body).delegate('form', 'submit', methods.checkForm);
$(document.body).delegate('form', 'submit',
                                  methods.submitFormIfCheckedFormIsTrue); 

然后在第一个(通用)处理程序中,您应该调用event.stopImmediatePropagation() method以防止调用其他处理程序(注意只是返回false会阻止默认值并停止事件冒泡进一步,但它不会阻止其他该级别的处理程序来自运行):

methods.checkForm = function (e) {
  if (!$(this).isVerified()) {
      e.stopImmediatePropagation();
      return false;
  }
  return true;
};  

(顺便说一句,问题中显示的代码遗漏了.delegate()调用中的事件(第二个参数) - 我已将其放入我的代码中。)

或者直接绑定两个处理程序而不是使用.delegate()。说到使用.delegate(),如果您使用的是最新版本的jQuery,您可能希望切换到使用新的do-everything事件绑定方法.on()

  

“会发生什么,在checkForm函数之前或期间触发submitFormIfCheckedFormIsTrue函数”

绝对是在之前,而不是在期间。 (在几乎所有浏览器中)JavaScript在单个线程上运行,因此您不会同时运行两个函数。