setTimeout与事件绑定/解除绑定;什么更有效?

时间:2012-07-06 05:01:53

标签: javascript jquery dom

我遇到需要使用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这样的网站,但我不知道测量这样的内容是否真的有用。

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

1 个答案:

答案 0 :(得分:1)

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

但另一种方法是使用.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/