3

我正在定义一个自定义元素

customElements.define("my-button", class extends HTMLButtonElement {
  onclick() {
    console.log("bar");
  }
}, { extends: "button" })

https://jsfiddle.net/tuxkjp3q/

但是当我点击它时,什么也没有发生。

为什么会这样?如何在不覆盖构造函数的情况下将事件处理程序附加到类的每个实例?

编辑:

当我检查 DOM 对象时,有一个 onclick 处理程序,但它不起作用。这令人困惑

在此处输入图像描述

编辑2:

进一步的发现,当从原型中省略时,定义一个处理程序是可行的

customElements.define("my-button", class extends HTMLButtonElement {
  constructor() {
    super();
    this.onclick = () => console.log("bar");
  }
}, { extends: "button" })

但是当原型包含 时onclick,相同的处理程序不再起作用

customElements.define("my-button", class extends HTMLButtonElement {
  onclick() {
    console.log("bar");
  }

  constructor() {
    super();
    this.onclick = () => console.log("bar");
  }
}, { extends: "button" })

如果我们能得到这个现象的解释,我会非常高兴。

编辑 3:

如果有人遇到同样的问题,我想出了一个解决方法。可能值得注意的是,只有在实例化类的直接原型中定义的处理程序才会被附加,这有利于性能,但可能存在逻辑缺陷。无论如何,它可以根据您的要求进行调整。

// Only in the base class
constructor() {
  super();

  for (let prop of Object.getOwnPropertyNames(this.constructor.prototype)) {
    if (prop.indexOf("on") === 0) {
      this.addEventListener(prop.substring(2).toLowerCase(), this.constructor.prototype[prop]);
    }
  }
}

我仍然非常有兴趣了解其中的原因。

4

3 回答 3

3

问题是您需要定义单击的侦听器...而不是 onClick 函数

class CustomButton extends HTMLButtonElement  {
  constructor() {
    super();

    this.addEventListener('click', () => {
      console.log('clicked');
    });
  }
}

customElements.define('custom-button', CustomButton, { extends: "button" });

html

<button is="custom-button">
  Hi
</button>
于 2020-10-04T01:50:33.027 回答
0

您真正所做的只是onclick为您的自定义元素创建一个属性并为其分配一个功能。仅仅因为它被命名onclick并不意味着系统知道这是一个click事件,因为您正在制作自己的元素。您将需要为您的自定义元素创建一个自定义事件。

于 2020-10-04T16:43:06.593 回答
0

您在附加所有以on开头的处理程序时非常直率

猜猜可能有多少:

document.body.append(
  ...Object.getOwnPropertyNames(window).filter(prop => prop.indexOf("on") === 0)
  .map((prop, idx, arr) => {
    let div = document.createElement("div");
    div.innerHTML = `${arr.length-idx} &nbsp; ${prop}`;
    return div;
  }));

您不必使用addEventListener;

在组件中使用(的)this.onclick=处理程序可以更加灵活,
因为组件的用户可以轻松地覆盖它。
同组件addEventListener作者必须提供removeListener方法;否则用户无法移除监听器。

有关不同 JavaScript 事件模型的信息:

于 2020-11-15T10:31:17.990 回答