jQuery:处理多个事件以获得最佳性能的最佳方法

3
如果我需要使用jQuery的.on()多个事件附加到同一个元素上,我应该将所有事件组合到一个调用中,并使用event.type来区分它们吗?还是应该为每个事件单独使用一个.on()调用? 组合事件:
$('#main').on('mouseenter mouseleave click', '.myElement', function(event) {
    if (event.type == 'click') {
       return false;

    } else if (event.type == 'mouseenter') {
        $(this).addClass('active');

    } else if (event.type == 'mouseleave') {
        $(this).removeClass('active');
    }
}

分离事件:

$('#main').on('click', '.myElement', function(event) {
   return false;
}

$('#main').on('mouseenter', '.myElement', function(event) {
    $(this).addClass('active');
}

$('#main').on('mouseleave', '.myElement', function(event) {
    $(this).removeClass('active');
}

哪一个是最快的?
【编辑】额外细节:显然,我们需要考虑两个方面,第一个是当页面加载完成并且事件处理程序被设置时,只使用一个.on()调用会更快。然而,第二个方面是这些事件实际上将何时触发,当鼠标悬停或单击.myElement时,我认为这更重要,因为它会发生很多次,而.on()调用仅会被调用一次(或更多次,但仍少于事件本身)。

3个回答

4
你必须区分绑定事件(将回调函数附加到事件)和实际处理触发的事件(调用/执行回调函数)。第一个可能每个页面只发生一次,而后面可能根据用户活动而发生数百次。
  • 如果你只考虑事件绑定 - 它在文档准备好时(最终)和每次DOM更改时(例如在Ajax Complete上)发生 - 那么使用仅带有一个回调函数的一个.on()调用会更快: http://jsperf.com/multiple-jquery-events/2

  • 如果您考虑处理被触发的事件-(即用户点击或悬停在.myElement上)-则将所有事件组合成一个回调并使用if语句区分它们也比具有多个回调更快:http://jsperf.com/multiple-jquery-events/4

这里是两个测试的组合结果:

绑定速度最快,事件处理速度也最快:

$('#main').on('mouseenter mouseleave click', '.myElement', function(event) {

    // Processing of the triggered event:
    if (event.type == 'click') {
        return false;

    } else if (event.type == 'mouseenter') {
        $(this).addClass('active');

    } else if (event.type == 'mouseleave') {
        $(this).removeClass('active');
    }
});

以上代码是推荐的语法。以下示例仅供参考。


绑定速度较慢约30%,事件处理速度较慢约50%:

$('#main').on('click', '.myElement', function(event) {
    return false;
});

$('#main').on('mouseenter', '.myElement', function(event) {
    $(this).addClass('active');
});

$('#main').on('mouseleave', '.myElement', function(event) {
    $(this).removeClass('active');
});

最慢的绑定方式,以及处理事件的速度慢了70%:

$('#main').on({
    mouseenter: function() {
        $(this).addClass('active');
    },
    mouseleave: function() {
        $(this).removeClass('active');
    },
    click: function() {
        return false;
    }
}, '.myElement');

绑定速度慢了约25%,并且处理事件最慢:

$('#main').on('click', '.myElement', function(event) {
    return false;
});

$('#main').on('hover', '.myElement', function(event) {
    $(this).addClass('active');
}, function() {
    $(this).removeClass('active');
});
绑定速度大约慢了20%,处理事件的速度慢了60%:
$('#main').on('click', '.myElement', function(event) {
    return false;

}).on('mouseenter', '.myElement', function(event) {
    $(this).addClass('active');

}).on('mouseleave', '.myElement', function(event) {
    $(this).removeClass('active');
});

0

我认为使用combined事件比separated事件更快。 因为当使用combined时,jquery.on()只会在jquery库中调用一次,然后它会在内部调用。如果是separated,则每次都需要调用jquery库。 如果您查看代码,则会发现,

 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
    var type, origFn;

    // Types can be a map of types/handlers
    if ( typeof types === "object" ) {
        // ( types-Object, selector, data )
        if ( typeof selector !== "string" ) {
            // ( types-Object, data )
            data = data || selector;
            selector = undefined;
        }
             /* here is looping if in case combined event then this
                loop will work and all your events will bound here */
             /* in case of seperated events
                loop will work only for selected event and it will bind*/
        for ( type in types ) {
            this.on( type, selector, data, types[ type ], one );
        }
        return this;
    }

如果您使用组合事件,会更容易一些,例如:

$('#main').on({
    mouseenter: function() {
        $(this).addClass('active');
    },
    mouseleave: function() {
        $(this).removeClass('active');
    },
    click: function() {
        return false;
    }
}, '.myElement');

这没有任何意义。为什么当jQuery在内部调用自身时会更快,你可以直接这样做:var $('#main').on().on().on() - Andreas Louv

-1
按预期,只有一个选择器的那个速度最快。请在此处查看测试结果:

http://jsperf.com/multiple-jquery-events

我还添加了几个其他完成相同任务的代码片段。这个代码是最好使用的:

$('#main').on('mouseenter mouseleave click', '.myElement', function(event) {
    if (event.type == 'click') {
        return false;
    } else if (event.type == 'mouseenter') {
        $(this).addClass('active');
    } else if (event.type == 'mouseleave') {
        $(this).removeClass('active');
    }
});

但第二个(case-switch)和最后一个(没有on())几乎同样快

$('#main .myElement').click(function(event) {
    return false;
}).mouseenter(function(event) {
    $(this).addClass('active');
}).mouseleave(function(event) {
    $(this).removeClass('active');
});

我认为你可能得到了一个错误的结果。jQuery只绑定一次事件,然后将其推送到堆栈中以添加更多事件。这也是为什么element.addEventListener在jsperf.com上看起来比jQuery.on慢的原因。 - Andreas Louv
1
另外,no on() 内部也使用了 .onhttp://james.padolsey.com/jquery/#v=1.7.2&fn=jQuery.fn.click - Andreas Louv
你的第二种方法与2个选择器语法(委托事件)不具备相同的目的。在你的第二个例子中,事件被添加到了.myElement而它们应该被添加到#main元素上,以便新添加的.myElement元素(例如通过ajax)也可以触发该事件。 - Community
@NULL 这就解释了为什么它会慢一些。 - Broxzier
另外,为什么您没有考虑提升#main (var a = $('#main');)。然后在真正的操作中,将重点放在绑定事件上,而不是选择器速度上,以提高性能? - Andreas Louv
@Broxzier 不,这并不完全是由那个解释的;这是选择器的问题。 - Andreas Louv

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