【问题标题】:JavaScript: remove an event listener from within that listener?JavaScript:从该侦听器中删除事件侦听器?
【发布时间】:2011-02-08 17:36:36
【问题描述】:

我一直想知道这种方法有多干净——从那个监听器中删除一个事件监听器。

更新:

在内部,我保留了对象和侦听器的哈希值,因此我可以从任何地方删除事件侦听器。我只是担心将其从内部移除。这样的行动真的有用吗?

更新

我在问关于 addEventListener、removeEventListener 的东西。

【问题讨论】:

  • 我们说的是addEventListener还是.onxxx =

标签: javascript garbage-collection dom-events


【解决方案1】:

您可以通过once 选项让侦听器只执行一次,然后自行移除。文档:https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters

例子:

  element.addEventListener('eventname', (ev) => {
    console.log("event is captured only once.");
    // do more stuff...
  }, { once: true });

从上面的同一个文档链接中,现代浏览器支持很好,但不适用于 Internet Explorer。

【讨论】:

  • 是的...当我问原始问题时,我认为这不可用:D
  • 但我认为简单地拥有一个命名的事件处理程序,然后从处理程序中实际删除它是最好的和最符合跨浏览器的方法。
  • 另外,在某些应用程序中,一次是不够的——“一次”只是一种特殊情况。
  • 我认为这是 2020 年大多数用途的最佳方式,因为大多数人想要删除监听器的原因是让它只执行一次。然而,在移除的条件不是单例执行的情况下,这个解决方案就不是很好了。我想您仍然可以通过设置once 并在满足任意条件时在回调函数中添加另一个侦听器来使其工作,本质上是进行某种奇怪的递归,但此时其他解决方案显然更干净。
【解决方案2】:

我刚刚看到这个是因为我想知道确切同样的问题!

arguments.callee 是你的朋友...

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee

所以你有

blah.addEventListener('click',function(e){
    e.source.removeEventListener('click', arguments.callee);
    blee bloo bleep
});

这适用于 Titanium Appcelerator,因此它应该也适用于 javascript(因为它们是相同的东西)

请注意,在此示例中,不要将 () 添加到 arguments.callee 的末尾,除非您喜欢看到...bah dum tish!

事实上,如果你不想使用 arguments.callee,这也可能有效(未经测试):

blah.addEventListener('click', anyThingYouWantHere = function(e){
    e.source.removeEventListener('click', anyThingYouWantHere);
    blee bloo bleep
});

其中“anythingYouWantHere”是您想要的任何变量名称 ~ 您在添加函数时实际上是在“命名”该函数。

【讨论】:

  • 这在 ES5 严格模式下是不允许的,不是吗?
  • 哈!我什至从来没有知道这样的事情存在。 ANYhoo,我四处逛逛,发现了这个stackoverflow.com/a/1335595/1061426,这似乎表明它仍然存在。此外,我为 arguments.callee 引用的链接也没有提到它已被弃用。链接确实提到()变体不起作用,但我们在这里没有使用它...由于stackoverflow
  • 嗨!你的第二个例子是一个赋值,它适用于带有赋值运算符'='而不是':'的javascript
  • @user 看到你上面的评论
【解决方案3】:

我刚刚做了一个包装函数,它会生成一个自毁事件监听器:

let addSelfDestructingEventListener = (element, eventType, callback) => {
    let handler = () => {
        callback();
        element.removeEventListener(eventType, handler);
    };
    element.addEventListener(eventType, handler);
};

到目前为止效果很好:)

【讨论】:

  • 这很好用,不是所有的浏览器都支持{once: true}!!这应该是推荐的答案。
【解决方案4】:

@bharal 回答现在给了我这个解决方案:

//example
addBlurListener(element, field) {
    const listenToBlur = (e) => {
        e.target.removeEventListener(e.type, listenToBlur);
        //your stuff
    };
    element.addEventListener('blur', listenToBlur);
},

【讨论】:

    【解决方案5】:

    您可以尝试这样的事情,具体取决于它的名称:

    some_div.onclick = function () {
        ...
        this.onclick = null;
        // or: some_div.onclick = null;
    };
    

    或者是你关心的事件listeners?因为这些有点复杂。

    【讨论】:

    • 是的听众...我认为处理程序和听众是一样的,不是吗?
    • @jayarjo 一个元素每个事件只能有一个处理程序,但可以有任意数量的侦听器。无论如何,这是我的理解。
    【解决方案6】:

    如果您使用 jQuery,您可能会公开一些与事件处理程序交互的便捷方法——请参阅 bind()/unbind()、delegate()/undelegate()、one() 和 similar methods

    我对其他框架没有太多经验,但我想它们提供类似的功能。如果您根本不使用框架,@sdleihssirhc 有一个可以接受的答案。

    编辑:啊,也许您正在寻找更像addEventListener()removeEventListener() 的东西。同样,框架将为您的交互提供一些便利,并在某些情况下为您省去重新发明轮子的麻烦。

    【讨论】:

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