javascript - 无法移除 eventListener,尝试了 6 小时
问题描述
我已经尝试了几个小时删除事件侦听器而没有任何成功。
由于我进行的测试,我了解到问题可能在于听众参考。
这是代码。为了清楚起见,我剥离并简化了所有内容。
const COMPLETE = 'complete';
let dispatcher = new EventTarget;
class Template {
complete(e){
e.currentTarget.removeEventListener(COMPLETE, this.complete);
console.log('I run only once');
}
}
let child = new Template();
child.exe = function(){
dispatcher.addEventListener(COMPLETE, this.complete.bind(this));
}
child.exe();
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
当然在控制台中你可以读三遍“我只运行一次”。
我所做的测试涉及额外的变量“functionReference”,我在其中存储侦听器引用。然后它工作。
let functionReference
const COMPLETE = 'complete';
let dispatcher = new EventTarget;
class Template {
complete(e){
e.currentTarget.removeEventListener(COMPLETE, functionReference);
console.log('i run only once');
}
}
let child = new Template();
child.exe = function(){
functionReference = this.complete.bind(this);
dispatcher.addEventListener(COMPLETE, functionReference);
}
child.exe();
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
现在在控制台中只有一次“我只运行一次”。
怎么了?为什么我不能删除那个监听器?
*****更新/解决方案如下 ***非常感谢 Teemu 和 amrender singh
感谢 amrender singh 的解释!并感谢 Teemu 的好主意和解决方案!非常感谢您的快速帮助!多年来,我没有被困得这么厉害。
以下 Teemu 解决方案:
const COMPLETE = 'complete';
let dispatcher = new EventTarget;
class Template {
constructor(){
this.complete = (e)=>{
e.currentTarget.removeEventListener(COMPLETE, this.complete);
console.log('i run only once');
}
}
}
let child = new Template();
child.exe = function(){
dispatcher.addEventListener(COMPLETE, this.complete);
}
child.exe();
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
dispatcher.dispatchEvent(new Event(COMPLETE));
或者,可以存储对侦听器的引用并将其作为变量传递。
解决方案
来自 MDN:
bind() 方法创建一个新函数,在调用该函数时,将其 this 关键字设置为提供的值,并在调用新函数时提供的任何参数之前具有给定的参数序列。
在第一个示例中:
dispatcher.addEventListener(COMPLETE, this.complete.bind(this));
绑定创建一个新函数并将其附加为处理程序。这就是为什么您无法删除事件侦听器的原因,因为您之前使用 bind 附加的事件侦听器与您的完整方法不同。
在您的第二个示例中:
functionReference = this.complete.bind(this);
dispatcher.addEventListener(COMPLETE, functionReference);
您正在将 bind 返回的新函数注册为侦听器,然后将其删除,因为在添加/删除中,侦听器都是相同的,这就是它被删除的原因。
推荐阅读
- javascript - 在 JS 中保存/读取 cookie?
- c++ - 在 CUDA 扩展 lambda 中捕获变量时出现内存错误
- wordpress - FacetWP,从今天开始查询
- c++ - 理解 Node.js 的 napi_value 类型的定义
- java - 有人可以解释下面的代码是如何工作的
- mysql - mysql not using index on simple OR condition
- sass - 使用颜色对象时,SASS 功能变暗和变亮不起作用
- python - Pandas:按两个参数分组并按第三个参数排序
- keycloak - 在后端 API 前使用 Keycloak Gatekeeper
- php - 此路由不支持 DELETE 方法。支持的方法:GET、HEAD、POST。在 laravel 中