我一直想知道这种方法有多干净——从该监听器中删除事件监听器。
更新:
在内部,我保留了对象和侦听器的哈希值,因此我可能可以从任何位置删除事件侦听器。我只是关心将其从内部移除。这样的行动真的能起到作用吗?
更新
我问的是有关 addEventListener、removeEventListener 的内容。
您可以传递
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。
我刚刚看到这个是因为我想知道完全相同的问题!
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”是您想要的任何变量名称〜您在添加函数时实际上是在“命名”该函数。
let addSelfDestructingEventListener = (element, eventType, callback) => {
let handler = () => {
callback();
element.removeEventListener(eventType, handler);
};
element.addEventListener(eventType, handler);
};
到目前为止效果很好:)
//example
addBlurListener(element, field) {
const listenToBlur = (e) => {
e.target.removeEventListener(e.type, listenToBlur);
//your stuff
};
element.addEventListener('blur', listenToBlur);
},
如果您希望监听器只触发一次,可以使用以下代码:
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();
});
some_div.onclick = function () {
...
this.onclick = null;
// or: some_div.onclick = null;
};
或者是您关心的事件
听众?因为这些有点复杂。
类似方法。
我对其他框架没有太多经验,但我想它们也提供类似的功能。如果您根本不使用框架,@sdleihssirhc 有一个可接受的答案。编辑:啊,也许您正在寻找更像
addEventListener() 和 removeEventListener() 的东西。同样,框架将为您的交互提供一些便利,并在某些情况下省去您重新发明轮子的麻烦。
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() 相比,放弃我最喜欢的清理事件的新方法。