【问题标题】:Remove anonymous event listeners before adding any new ones在添加任何新事件侦听器之前删除匿名事件侦听器
【发布时间】:2013-06-27 18:19:06
【问题描述】:

编辑:我需要调用一个获取数据并重新加载页面内容的函数。但是一旦另一个函数获取了数据(webSql),就必须调用它。我不能使用 WebSql 回调,因为变量超出了范围。所以我创建了一个自定义事件并在第二个函数范围内添加了一个监听器。因此,当获取数据时,我将在第一个函数范围内调度事件。现在的问题是,如果页面多次重新加载,监听器将被添加多次,并且所有的都将被调用,这是我不想要的。

我需要确保只有一个函数正在侦听自定义事件。现在正在删除侦听器,一旦它像这样调用:

document.addEventListener("customEvent", function () {
  actualCallBack(var1, var2); // Since I need to pass parameters I need to use callBack within an anonymous function.
  this.removeEventListener("customEvent", arguments.callee, false);
}, false);

但问题是匿名函数只有在首先被调用后才会被删除。听众有可能获得多次增加。如何在添加新事件侦听器之前删除事件侦听器?

document.removeEventListener("customEvent");
document.addEventListener(...);

如果使用变量函数,我可以删除它,但我需要将一些参数传递给回调,所以我需要使用匿名函数。

【问题讨论】:

  • IIRC, cloneNode 克隆除事件侦听器之外的所有内容。不过,在document-scope 中这样做可能会很有趣……
  • 一种方法是将整个事件绑定放在自定义函数中。然后,该函数可以保留对传递的处理程序的引用,并确保只绑定一个处理程序。当然,这要求处理程序仅通过该函数绑定到元素。
  • 我不明白你为什么必须使用匿名函数的解释。这是一个相关的问题顺便说一句:stackoverflow.com/questions/4386300/…
  • @FelixKling 我没有将事件绑定到 div 元素。我在另一个函数中使用 dispatchEvent 调用事件侦听器。所以我需要删除之前添加的任何内容。
  • @basilikum 我已经编辑了问题。我需要传递一些参数,所以我将 callBack 包装在一个匿名函数中。

标签: javascript


【解决方案1】:

使用 felix 的建议

var setSingletonEventListener = (function(element){
    var handlers = {};
    return function(evtName, func){
        handlers.hasOwnProperty(evtName) && element.removeEventListener(evtName, handlers[evtName]);
        if (func) {
            handlers[evtName] = func;
            element.addEventListener(evtName, func);
        } else {
            delete handlers[evtName];
        }
    };
})(document);

setSingletonEventListener("custom event", function(){

});

//replaces the previous
setSingletonEventListener("custom event", function(){

});

//removes the listener, if any
setSingletonEventListener("custom event");

【讨论】:

  • 试过了,但它被调用了两次。也许我做错了什么——Fiddler Link jsfiddle.net/NeT7W/1
  • @2-Stroker:修正了代码,它必须是element.removeEventListener(evtName, handlers[evtName])
  • 如果我们不想在 document 上监听,如何传递自定义 DOM 元素?
【解决方案2】:

将您已应用监听器的地方存储起来,如果尚未添加,则仅添加它。

【讨论】:

  • 本可以使用它,但在我的情况下,唯一的持久变量将是 web Sql DB 中的变量。
【解决方案3】:

这是一种方法:

var singletonEventListenerFor = function (element, eventName) {
    var callback = null;
    element.addEventListener(eventName, function () {
        callback && callback();
    });
    return function (set) {
        callback = set;
    };
};

测试:

var event = document.createEvent("Event");
event.initEvent("customEvent", true, true);

var listener = singletonEventListenerFor(document, "customEvent");

var counter = 0;

listener(function () {
    console.log(++counter);
});

// counter === 1
document.dispatchEvent(event);

// Remove the listener
listener();
// This shouldn't increment counter.
document.dispatchEvent(event);

listener(function () {
    console.log(++counter);
});

// counter === 2
document.dispatchEvent(event);
// counter === 3
document.dispatchEvent(event);

console.log('3 === ' + counter);

http://jsfiddle.net/Dogbert/2zUZT/

如果您愿意,可以通过返回一个带有 .set(callback).remove() 函数的对象来改进 API,而不是使用一个函数来完成这两项工作。

【讨论】:

    猜你喜欢
    • 2011-03-07
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    相关资源
    最近更新 更多