1

我有一种情况,我需要将 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之类的网站,但我不知道它是否真的有助于衡量此类内容。

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

4

1 回答 1

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/

于 2012-07-06T06:00:25.147 回答