所以我正在寻找一种为自定义元素设置 ES6“抽象”基类的方法,该基类在子元素的第一次实例化时进行自我注册(window.customElements.define)。
我想出的方法如下:
class MyBase extends HTMLElement {
constructor(tag, child) {
MyBase.register(tag, child);
super();
if(this.constructor.name === MyBase) {
throw new Error('Error: Do not instantiate base class!');
}
}
static register(tag, child) {
if(!window.customElements.get(tag)) {
window.customElements.define(tag, child);
}
}
}
class MyChild extends MyBase {
constructor() {
super(MyChild.Tag(), MyChild);
if(window.customElements.get(MyChild.Tag())) {
console.log(`${this.constructor.name} registered!`)
}
}
static Tag() {
return "my-child";
}
}
const NiceChild = new MyChild();
有没有办法避免静态和 MyBase 构造函数参数?我尝试了各种方法,但无法找出更优雅的解决方案,因为必须在调用 HTMLElement 构造函数之前调用注册。另外,如果直接实例化MyBase,我当然不希望进行注册。
构造函数不是您注册自定义元素的地方:您在声明类后“立即”注册它,然后如果您希望代码仅在浏览器完成加载后才开始运行,请等待它:
class Thing extends HTMLElement {
constructor() {
// do nothing
}
connectedCallback() {
// do meaningful things
}
}
class OtherThing extends Thing {
// ...
}
customElements.define(`other-thing`, OtherThing);
await customElements.whenDefined(`other-thing`);