我一直在想,.addEventListener
方法中的第二个参数,是否可以调用“(自定义)类方法”,而不是函数?
比如以下代码会起作用吗?
var object = new ClassName();
document.getElementById('x').addEventListener('click', object.method, false);
我一直在想,.addEventListener
方法中的第二个参数,是否可以调用“(自定义)类方法”,而不是函数?
比如以下代码会起作用吗?
var object = new ClassName();
document.getElementById('x').addEventListener('click', object.method, false);
不行,你写的代码是错误的,因为在调用method
时没有将object
作为上下文来执行。在method
内部,this
会被设置为触发事件的DOM元素。
如果你想要调用方法并保留上下文,可以使用一个函数来封闭object
变量:
var object = new ClassName();
document.getElementById('x').addEventListener('click', function () {
object.method()
}, false);
我刚刚尝试了一种更直接的方法,它似乎有效,并且我认为它非常简洁。我只是将bind(this)
添加到addEventListener()
的参数中。不要在不需要时使它变得复杂...
class HTMLExample extends HTMLElement{
constructor(){
super();
this.count = 0;
this.addEventListener('click', this.onClick.bind(this), false);
}
onClick(event){
let prevCount = this.count;
this.count++;
let msg = `Increased Count from ${prevCount} to ${this.count}`;
document.getElementById("log").innerHTML += `${msg}<br/>`;
}
}
可以通过绑定来实现。
下面我正在创建一个Web组件。这是大多数浏览器支持的功能。
为了创建这个Web组件,我正在创建一个扩展HTMLElement
类的类。就JavaScript而言,这只是另一个常规类。
现在,我希望我的Web组件表现得像一个按钮。 每次单击我的标签时,我希望计数器增加。
注意:三个点表示“更多代码”在那里。
因此,我在构造函数中创建一个将保存计数的变量:
constructor(){
...
this.count = 0;
...
接下来,我会添加一个监听器来检测当我的 Web 组件被点击时,并调用 onClick
方法:
constructor(){
...
this.count = 0;
...
this.addEventListener('click', this.onClick, false);
}
onClick(event){
let prevCount = this.count;
this.count++;
let msg = `Increased Count from ${prevCount} to ${this.count}`;
document.getElementById("log").innerHTML += `${msg}<br/>`;
}
onClick旨在增加计数器并打印计数器的上一个和当前值; 但是,这里存在问题!!!
问题出在这一行this.count++;
。关键字this
没有引用HTMLExample
类的实例。原因是使用addEventListener
添加的函数将把绑定元素作为this
引用,而不是函数或对象。
因此,您必须将由addEventListener
使用的该函数绑定到您的类实例上,方法是添加以下代码:
this.onClick = this.onClick.bind(this);
onClick
中使用关键词 this
时,this
将会引用类 HTMLExample
的实例。请查看下面的代码并运行它,我认为这样会更加清晰:
class HTMLExample extends HTMLElement{
constructor(){
super();
this.count = 0;
this.onClick = this.onClick.bind(this);
this.addEventListener('click', this.onClick, false);
}
onClick(event){
let prevCount = this.count;
this.count++;
let msg = `Increased Count from ${prevCount} to ${this.count}`;
document.getElementById("log").innerHTML += `${msg}<br/>`;
}
}
customElements.define('example-component', HTMLExample);
example-component{
cursor: pointer;
border: 1px solid black;
background: lightgray;
padding: 2px;
}
<example-component>Button</example-component>
<div id="log"></div>
大多数答案使用Function.prototype.bind(),但你可以通过简单编写代码来实现。
class EventHandler {
constructor(element) {
element.addEventListener('mousedown', this.handler);
}
// just declare the method as a property with arrow function.
hander = () => {
console.log(this);
}
}
我在codepen.io上编写了完整的可工作代码示例。
myclass= function(){};
myclass.prototype.addSystemEvents = function(){
var scope = this;
window.addEventListener( 'resize', function(){scope.onWindowResize();}, false);
}
myclass.prototype.onWindowResize = function(){
//do whatever
}
是的,这是可能的。您需要调用该方法并保留上下文,在函数中使用闭包对象变量:
var object = new ClassName();
document.getElementById('x').addEventListener('click', function (e) {
object.method(e)
}, false);
是的,这是可能的,只需要注意上下文。例如:
ClassName.prototype.click_handler = function(el) {
// Here 'this' doesn't refer to the instance
// of ClassName but to the element clicked
}
var object = new ClassName();
document.getElementById('x').addEventListener('click', object.click_handler, false);
对于使用 TypeScript 或 Babel/Transpilation 的开发者,以下是我能想到的最干净的方法,当然还有改进的空间!
class Person {
name = "bobby"
sayGoodbyBound = this.sayGoodby.bind(this);
sayGoodby() {
console.log('Goodbye, my name is', this.name);
}
}
const person = new Person();
let element = document.createElement("button")
element.addEventListener("click", person.sayGoodbyBound);
element.click()
// remove same one
element.removeEventListener("click", person.sayGoodbyBound);
method
是如何定义的?它需要做什么?它可能会“工作”,也可能不会。 - cookie monster.method
确实是一个函数,它将作为处理程序传递,但是不知道它的功能,它可能会或可能不会“工作”。 - cookie monsterobject.method
仍然是一个普通函数,对于addEventListener
来说它看起来就像任何其他函数一样。函数与被分配为属性值的对象之间没有隐含的关系。假设你有function foo() {...}; obj.method = foo; obj2.method2 = foo; var bar = foo;
。那么,在你的逻辑之后,foo
现在是什么?它“属于”什么? - Felix Kling