jquery设置处理程序的顺序

时间:2012-03-27 15:54:54

标签: jquery

我有一个div MyClass类,我想连接两个处理程序。这个类是动态生成的,这就是我正在做的事情:

$('#MainDiv').on({
 click: function () { Handler1($(this)); }
}, '.MyClass');

$('#SpecialChildDiv').on({
 click: function () { Handler2($(this)); }
}, '.MyClass');

如何控制首先调用哪个处理程序? Handler2会做一些额外的工作但是并没有在每个MyClass上调用它,因为它不在SpecialChildDiv中。我希望Handler 2被称为AFTER Handler1。

感谢。

2 个答案:

答案 0 :(得分:1)

因为SpecialChildDiv可能是MainDiv的后代,所以它将首先被调用。这是因为事件从目标中冒出来,并按顺序调用沿途向上发现的处理程序。

一种可能性是使用Handler2SpecialChildDiv处理程序异步中调用setTimeout

$('#MainDiv').on({
   click: function () { 
       Handler1($(this)); 
   }
}, '.MyClass');

$('#SpecialChildDiv').on({
   click: function () { 
       setTimeout($.proxy(function() {
           Handler2($(this));
       }, this), 0);
   }
}, '.MyClass');

因此,处理程序本身将立即被调用,但是Handler2函数将在Handler1被调用之后才会运行。

我还使用$.proxy在传递给this的函数中保留了正确的setTimeout值。


有点偏离主题,但如果您更改Handler1Handler2以便this是对元素的引用,而不是将其作为参数传递,则可以使代码更清晰...

$('#MainDiv').on({
   click: Handler1
}, '.MyClass');

$('#SpecialChildDiv').on({
   click: function () { 
       setTimeout($.proxy(Handler2, this), 0);
   }
}, '.MyClass');

您只需在函数内部执行$(this)即可将元素包装在jQuery对象中。虽然如果有其他参数可以通过,这可能没有用。


根据您在下面的评论,似乎需要将此技术应用于各种后代元素。

要干掉代码,您可以为点击处理程序创建一个工厂......

function async_handler_factory(the_handler) {
    return function() {
        setTimeout($.proxy(function() {
           the_handler($(this));
        }, this), 0);
    };
}

...然后像这样使用它......

$('#MainDiv').on({
   click: Handler1
}, '.MyClass');

$('#SpecialChildDiv').on({
   click: async_handler_factory(Handler2)
}, '.MyClass');

$('#AnotherChildDiv').on({
   click: async_handler_factory(Handler3)
}, '.MyClass');

所以这是相同的原则。只需将HandlerN函数传递给async_handler_factory,它就会创建并返回click处理函数,它通过调用HandlerN来执行与原始代码相同的操作。 setTimeout


为了避免混淆$.proxy,这里有一个消除它的更新版本。

function async_handler_factory(the_handler) {
    return function() {
        var self = this;
        setTimeout(function() {
           the_handler($(self));
        }, 0);
    };
}

这表明实际上是setTimeout使您的解决方案有效。


编辑:在不同的地方为async_handler_factory提供了不同的名称。固定的。

答案 1 :(得分:0)

所以不要在点击时调用第二个 - 在第一个处理程序完成后调用它:

$('#MainDiv').on({
    click: function (e) { 
        Handler1($(this)); 
        if ($(e.target).attr('id')==="SpecialChildDiv") {
            specialChildClick();
        }
    }
}, '.MyClass');

specialChildClick = function () {
    Handler2($('#SpecialChildDiv')); 
}