我正在定义一个自定义元素
customElements.define("my-button", class extends HTMLButtonElement {
onclick() {
console.log("bar");
}
}, { extends: "button" })
https://jsfiddle.net/tuxkjp3q/
但是当我单击它时,什么也没有发生。
这是为什么?如何在不覆盖构造函数的情况下将事件处理程序附加到类的每个实例上?
当我检查DOM对象时,有一个onclick处理程序,但是没有起作用。这很混乱
进一步的发现,从原型中省略时,定义了处理程序。
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" })
如果能对此现象做出解释,我将非常高兴。
如果有人遇到相同的问题,我想出一个解决方法。可能值得注意的是,只有实例化类的直接原型中定义的处理程序才会被附加,这对性能有好处,但逻辑上可能有缺陷。无论如何,它可以根据您的要求进行调整。
// 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]);
}
}
}
我仍然非常有兴趣了解原因。
答案 0 :(得分:3)
问题是您需要定义click的侦听器...而不是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>
答案 1 :(得分:0)
您真正要做的就是为您的自定义元素创建一个onclick
属性,并为其分配一个功能。仅仅因为它被命名为onclick
并不意味着该系统知道它是click
事件,因为您正在制作自己的元素。 You will need to create a custom event for your custom element.
答案 2 :(得分: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} ${prop}`;
return div;
}));
您不必使用addEventListener
;
在组件 中使用( old )this.onclick=
处理程序,
因为该组件的用户可以轻松覆盖它。
使用addEventListener
组件的 author 必须提供一种removeListener
方法;否则用户将无法删除侦听器。
有关不同JavaScript事件模型的信息: