ES6 Class: access to 'this' with 'addEventListener' applied on method
本问题已经有最佳答案,请猛点这里访问。
在这个ES6脚本中,click事件不起作用,因为
如何将一个事件关联到一个方法而不释放作用域?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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问题,但其核心是
1 | this.elm.addEventListener('click', this.sayHello); |
和
1 2 | var fn = this.sayHello; this.elm.addEventListener('click', fn); |
您正在传递一个函数作为事件处理程序,但没有确保当调用
1 | this.elm.addEventListener('click', this.sayHello.bind(this)); |
或在ES6中,使用箭头函数:
1 | this.elm.addEventListener('click', evt => this.sayHello(evt)); |
但是请注意,这两个解决方案都会破坏您在
1 | this.elm.removeEventListener('click', /* what? */); |
您不再具有对所附加函数的任何引用,因此无法删除事件处理程序。
我建议两种选择:
1 2 3 4 5 | // 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); |
或
1 2 3 4 5 | // 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); |