在这个 es6 脚本中,点击事件不起作用,因为 sayHello
使用 this.elm
调用方法( <div>
) 作为 this
.
如何在不松开范围的情况下将事件关联到方法?
class player{
constructor (name) {
this.name = name;
this.elm = document.createElement('div');
this.elm.addEventListener('click', this.sayHello);
}
sayHello() {
console.log(this.name + ' say: "hello!"'); // 'undefined say 'hello!"';
}
kill() {
console.log(`RIP ${this.name} :'(`);
this.elm.addClass('dead');
this.elm.removeEventListener('click', this.sayHello);
}
}
这是一个通用的JS问题,但它的核心在于
this.elm.addEventListener('click', this.sayHello);
和
没什么不同
var fn = this.sayHello;
this.elm.addEventListener('click', fn);
您正在传递一个函数作为事件处理程序,但未确保在调用 fn
时 this
将设置为您想要的值。在 ES5 中执行此操作的最简单方法是
this.elm.addEventListener('click', this.sayHello.bind(this));
或者在 ES6 中,使用箭头函数:
this.elm.addEventListener('click', evt => this.sayHello(evt));
但是请注意,这两种解决方案都会破坏您在 kill
中的(已经略微破坏的)逻辑,因为
this.elm.removeEventListener('click', /* what? */);
您不再对附加的函数有任何引用,因此您无法删除事件处理程序。
我建议两种选择:
// Create a new function that is bound, and give it a new name
// so that the 'this.sayHello()' call still works.
this.boundSayHello = evt => this.sayHello(evt);
this.elm.addEventListener('click', this.boundSayHello);
this.elm.removeEventListener('click', this.boundSayHello);
或
// Bind the function with the same name and use `.bind` instead of the
// arrow function option.
this.sayHello = this.sayHello.bind(this);
this.elm.addEventListener('click', this.sayHello);
this.elm.removeEventListener('click', this.sayHello);