setTimeout vs. 事件绑定/取消绑定;什么更有效

setTimeout vs. Event binding/unbinding; what's more efficient?

本文关键字:绑定 什么 有效 vs 事件 setTimeout 取消      更新时间:2023-09-26

我有一个情况,我需要对点击事件使用 jQuery 的 $.fn.one() 函数,但我不希望它应用于事件的下一次出现(就像它通常所做的那样),我希望它立即应用于之后的发生,然后取消绑定(就像.one()通常所做的那样)。

我不希望.one()应用于第一次出现的原因是因为我从冒泡阶段早些时候调用的事件处理程序绑定到document,因此第一次document它将成为同一事件的一部分。我想知道下一次点击事件发生的时间。

注意:我不想使用.stopPropagation(),因为它可能会破坏我应用的其他部分。

以下是我想出的两个选项,尽管似乎必须有一个更优雅的解决方案。

双重绑定方法:

$(document).one('click', function() {
  $(document).one('click', callback);
});

setTimeout 方法:

setTimeout(function() {
  $(document).one('click', callback);
}, 1);

这两种方法都很好用,但这是我的问题。我不知道 setTimeout 或频繁事件绑定和取消绑定的性能影响是什么。如果有人知道,我很想听听。但更重要的是,我想就如何自己衡量这些东西来应对未来这样的情况提出一些建议。

我喜欢像 http://jsperf.com 这样的网站,但我不知道它是否真的有助于衡量这样的东西。

显然,如果有人看到更好的解决方案,我很想听。

我发现双绑定方法非常优雅 - 我认为它准确地反映了您的实际意图,并且只需要两行代码。

但另一种方法是不使用.one()您可以使用.on()并更新与第一个事件关联的事件对象,添加一个标志,以便回调在第一次调用时忽略它:

function oneCallback(e) {
    if (e.originalEvent.firstTimeIn)
        return;
    alert("This is the one after the current event");
    $(document).off("click", oneCallback);
}
$("div.source").click(function(e) {
    e.originalEvent.firstTimeIn = true;
    $(document).on("click", oneCallback);   
});

演示:http://jsfiddle.net/q5LG4/

编辑:为了解决您对不修改event对象(或任何您不拥有的对象)的担忧,您可以在闭包中存储 firstTime 标志。这是一个相当狡猾的.oneAfterThis()插件,它采用了这种方法:

jQuery.fn.oneAfterThis = function(eventName, callback) {
    this.each(function() {
        var first = true;
        function cb() {
            if(first){
                first = false;
                return;
            }
            callback.apply(this,[].slice.call(arguments));
            $(this).off(eventName,cb);
        }
        $(this).on(eventName, cb);
    });
};
$(someseletor).oneAfterThis("click", function() { ... });

敢肯定,这本可以做得更优雅(也许我应该费心看看jQuery是如何实现.one()的),但我只是想快速制作一些东西作为概念证明。

演示:http://jsfiddle.net/q5LG4/1/