假设我有以下代码:
class Sample {
constructor() {
this.value = 'something';
}
addClickListener(e) { // e is a dom element
let func = function(e) {
//what I want to be able to do:
this.doThing(e);
}
e.addEventListener('click', func, false);
}
removeClickListener(e) {
let func = function(e) {
//what I want to be able to do:
this.doThing(e);
}
e.removeEventListener('click', func, false);
}
doThing(p) {
//code
}
}
我希望能够从“func”中引用一个类方法并向它传递一个参数。对类的引用(例如 let this = self)不起作用,因为它会在每次调用函数和事件监听器的签名更改时创建一个新版本。
最佳答案
要删除事件监听器,您需要保留对要删除的函数的引用:
class Sample {
constructor() {
this.value = 'something';
// I've changed it from "let func" to "this.func" so we retain a reference
// I also moved it from addClickListener to the constructor so that we
// don't overwrite our reference when binding more elements to the
// same function
this.func = function(e) {
//what I want to be able to do:
this.doThing(e); // NOTE: You have another bug here. See comments
}
}
addClickListener(e) { // e is a dom element
// Replaced "func" with "this.func"
e.addEventListener('click', this.func, false);
}
removeClickListener(e) {
// Removed the new (unused) function
// Replaced "func" with "this.func"
e.removeEventListener('click', this.func, false);
}
doThing(p) {
//code
}
}
注意我在评论中说“注意:你这里有另一个错误”
调用事件监听器时,上下文(this
变量)更改为发出事件的元素。所以this.doThing
将尝试调用 doThing
在元素上 e
!
另请注意 e
元素(传递给 addClickListener
的参数不与e
事件(传递给this.func
的参数)
要修复此错误,您需要存储对该类的引用并在您的函数定义中使用该引用:
constructor() {
this.value = 'something';
let self = this;
this.func = function(e) {
self.doThing(e);
}
}
在这里self
将不会像this
那样被覆盖将,所以我们可以安全地使用它来引用类实例
更好的解决方案
当我重新阅读这个问题时,我意识到你的函数实际上只是在调用另一个函数。因此,为什么不将最终要运行的功能传递给addEventListener
呢? ?
class Sample {
constructor() {
this.value = 'something';
}
addClickListener(e) {
e.addEventListener('click', this.doThing, false);
}
removeClickListener(e) {
e.removeEventListener('click', this.doThing, false);
}
doThing(p) {
//code
}
}
请注意,这仍然会有 this
的问题被调用事件的元素替换,所以在 doThing
内你不能说 this.doOtherThing
调用第二类方法。如果您希望这样做,则需要使用 JavaScript 的 .bind()
创建一个绑定(bind)方法像这样的方法:
class Sample {
constructor() {
this.value = 'something';
this.boundMethod = this.doThing.bind(this);
}
addClickListener(e) {
e.addEventListener('click', this.boundMethod, false);
}
removeClickListener(e) {
e.removeEventListener('click', this.boundMethod, false);
}
doThing(p) {
//code
this.doOtherThing(p);
//more code
}
doOtherThing(p) {
//code
}
}
另一种选择
正如@evolutionxbox 所指出的,您也可以使用箭头函数。这个解决方案看起来像这样:
class Sample {
constructor() {
this.value = 'something';
this.boundMethod = p => { this.doThing(p); };
}
addClickListener(e) {
e.addEventListener('click', this.boundMethod, false);
}
removeClickListener(e) {
e.removeEventListener('click', this.boundMethod, false);
}
doThing(p) {
//code
this.doOtherThing(p);
//more code
}
doOtherThing(p) {
//code
}
}
这样做的原因是箭头函数是绑定(bind)方法的简写:
x => x + 1;
// Is functionally equivalent to:
(function(x) {
return x + 1;
}).bind(this);
很多人没有意识到箭头函数包含隐式的 bind
,并且对于 90% 的用例来说,这无关紧要(例如 array.map(x => x + 1)
不关心 this
的值)但是在类中这个简写实际上是有值(value)的,所以它已经成为一个相当普遍的模式在 JavaScript 类中使用箭头函数以避免覆盖 this
变量。
关于javascript - 如何删除类中的事件监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56079864/