如何将事件处理程序定义为元素 class 方法?

How to define event handler as elements class method?

我尝试将点击事件处理程序定义为元素 class 方法

为什么它不起作用?

class Component extends HTMLElement {
    ...
    onclick () {
      console.log(event)
    }
}

但它是这样工作的

class Component extends HTMLElement {
    constructor() {
        super()
        this.onclick = console.log
    }

}

当你做的时候

someElm.onclick = console.log

其中 someElm 是一个元素,您实际上是在 调用附加侦听器的 setter

console.log(Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'onclick'));

这就是 this.onclick = 起作用的原因。这不仅仅是一个简单的赋值 - 它会导致函数调用,并且浏览器需要该函数调用来注册侦听器的附件。

相比之下,原型中的 onclick 方法 不会调用 setter,因此它不会告诉浏览器添加侦听器;它只是将 属性 添加到实例的原型链中。

出于类似的原因,创建具有 onclick 属性 的对象,其中对象的 内部原型 也具有 onclick setter 不调用 setter:

const theProto = {
  set onclick(newVal) {
    console.log('setter invoked');
  }
};

// Works:
theProto.onclick = 'foo';

console.log('About to create new object, but setter will not be invoked');
const theInstance = Object.create(theProto, { onclick: () => console.log('Onclick in instance running') });

Why it is not working?

查看@CertainPerformance 的回答。

How to define event handler as elements class method?

您可以使用 addEventListener() 如下:

class Component extends HTMLElement {
    constructor() {
        super()
        this.addEventListener( 'click', this.onclick )
    }

    onclick( ev ) {
        console.log( ev.target, this )
    }
}

customElements.define( 'c-e', Component )
<c-e>Click Me</c-e>

请注意,它并不是真正的文字事件处理程序(但我想这就是您的意思)。

如果你想要一个真正的事件处理程序,你应该定义一个getter和一个setter。

ES7+方式

class CustomElement extends HTMLElement {
    onclick = () => {...}
}