JavaScript:从该侦听器中删除事件侦听器?

问题描述 投票:0回答:8

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

更新:

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

更新

我问的是有关 addEventListener、removeEventListener 的内容。

javascript garbage-collection dom-events
8个回答
70
投票

您可以传递

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。


18
投票

我刚刚看到这个是因为我想知道完全相同的问题!

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”是您想要的任何变量名称〜您在添加函数时实际上是在“命名”该函数。


12
投票
我刚刚制作了一个包装函数,它生成一个自毁事件侦听器:

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

到目前为止效果很好:)


4
投票
@bharal 的答案现在给了我这个解决方案:

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

2
投票

如果您希望监听器只触发一次,可以使用以下代码:

element.addEventListener('eventname', function callback(){}, { once: true });
    

或者使用包装器来做同样的事情:

function addOneTimeEventListener(element, event, callback) { const wrapper = e => { try {callback(e)} finally { element.removeEventListener(event, wrapper); }; } element.addEventListener(event, wrapper); } // example addOneTimeEventListener(document.body, 'click', e => { console.log('this message only show once.'); });
  

如果您想决定何时删除侦听器:

function addEventListener(element, event, callback) { const wrapper = e => { callback(e, () => element.removeEventListener(event, wrapper)); } element.addEventListener(event, wrapper); } // example let count = 0; addEventListener(document.body, 'click', (e, closeListener) => { console.log(`click:${++count}`); if(count == 3) closeListener(); });
    

1
投票
您可以尝试这样的方法,具体取决于它的名称:

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

或者是您关心的事件

听众?因为这些有点复杂。


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

类似方法

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

编辑:啊,也许您正在寻找更像

addEventListener()removeEventListener() 的东西。同样,框架将为您的交互提供一些便利,并在某些情况下省去您重新发明轮子的麻烦。


0
投票
最简单的答案是

addEventListener('',function,{once:true})

,但它的功能有点有限。我找到了一种更可定制的方式,所以我想分享一下。

addEventListener() 文档指出事件选项对象(允许 {once:true} 功能)也可以采用 abortSignal。可以从引用控制器对象的任何地方触发此中止信号!

这是我需要的功能,归结为一个简单的示例:

function eventCreator(){ let moveController = new AbortController() const onEscapeKey = (e:KeyboardEvent) => { if(e.key !== 'Escape') return /* ... do something useful */ moveController.abort() } const onMouseDown = (e:MouseEvent) => { if(e.button !== 0) return /* ... do something else useful */ moveController.abort() } const onMouseMove = () => { /* Do Something completely irrelevant to the other functions */ } document.addEventListener('mouseMove', onMouseMove, {signal:moveController.signal}) document.addEventListener('mousedown', onMouseDown, {signal:moveController.signal}) document.addEventListener('keydown', onEscapeKey, {signal:moveController.signal}) }
主函数创建(或绑定)它需要的所有子函数。当它将函数应用到各自的 DOM 元素时,它会传递一个新创建的 

abortSignal

在这种情况下,mouseMove 函数立即开始被调用。它会一直被调用,直到用户 a) 按退出键或 b) 按鼠标左键。当后一个事件发生时,所有 3 个事件侦听器都会收到要清理的信号。

在我的例子中,我让 mousemove 侦听器控制对象的位置,escape 侦听器删除该对象,然后单击侦听器放置该对象。

与存储函数引用和在一切完成后调用

removeEventListener() 相比,放弃我最喜欢的清理事件的新方法。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.