为web组件创建一个BaseComponent,并引用一次组件名称



我注意到,在我正在开发的一些web组件中,我一直在重复使用一些常见/重复的方法。当我在其中一个组件中更改方法时,如果我想在其他组件中进行改进,我必须打开每一个,然后对所有其他组件进行更改,这既繁琐又容易出错。因此,我试图创建一个BaseComponent,其他组件从中继承。

问题是,我想在一个地方定义组件名称,例如wc-thingy,保持干燥。然而,在两个地方需要这个名称:

  1. 要查找组件的模板(我将模板的id命名为TEMPLATE_<component_name>,例如TEMPLATE_wc-thingy
  2. customElements.define

下面是我尝试实现它的尝试,但我认为问题是this.constructor没有引用子类实例:

window.BaseComponent = class extends HTMLElement {
static componentName;
static define(componentName) {
this.constructor.componentName = componentName;
window.customElements.define(this.constructor.componentName, this);
}
constructor() {
super();
this.attachShadow({ mode: "open" });
const template = document.getElementById("TEMPLATE_" + this.constructor.componentName);
this.shadowRoot.appendChild(template.content.cloneNode(true));
console.log("Contructed", this.constructor.componentName)
}
sayHello() {
console.log("Hello");
}
};
(class extends window.BaseComponent {
sayBi() {
console.log("K Bi, thxns!");
}
}).define('wc-thingy')
<wc-thingy>thingy here</wc-thingy>

+1用于创建您自己的BaseComponent

-392.176/112如果你现在认为自己很棒,并像其他60+BaseClasses 一样向世界出售

Web组件名称采用this.nodeName(大写(或this.localName(小写(

<template id="WC-FOO">foo:<slot></slot></template>
<template id="WC-BAR">bar:<slot></slot></template>
<wc-foo>FOO</wc-foo>
<wc-bar>BAR</wc-bar>
<script>
class BaseComponent extends HTMLElement {
constructor() {
const template = () => document.getElementById(this.nodeName).content;
super().attachShadow({mode:"open"})
.append(template().cloneNode(true));
console.log("Contructed", this.nodeName , this.localName)
}
};
customElements.define("wc-foo", class extends BaseComponent {});
customElements.define("wc-bar", class extends BaseComponent {});
</script>

只需将组件名称存储为子类上的静态访问器属性,而不是BaseElement类(扩展时不会继承静态属性(。属性是只读的(只有一个getter(。使其可写是没有意义的,因为您不希望TAG_NAME从外部更改。

在静态方法的末尾返回this也允许链接调用,例如,在下面的示例中,对define()的调用后面跟着对publish()的调用(它将您的类发布在您可以传递的对象上,如果您不传递任何对象,则默认为window(:

class BaseComponent extends HTMLElement {
static define() {
// When called from your subclass, `this` points to that class
console.log(this.TAG_NAME);
window.customElements.define(this.TAG_NAME, this);
return this;
}

static publish(target = window) {
target[this.TAG_NAME.replace(/(^w|-w)/g, x=>(x[1] ?? x[0]).toUpperCase())] = this;
return this;
}
constructor() {
super();
this.attachShadow({ mode: "open" });
const template = document.getElementById(
"TEMPLATE_" + this.constructor.TAG_NAME
);
this.shadowRoot.appendChild(template.content.cloneNode(true));
console.log("Contructed", this.constructor.TAG_NAME);
}
sayHello() {
console.log("Hello");
}
}
(class extends BaseComponent {
static get TAG_NAME() {
return "wc-thingy";
}
sayBi() {
console.log("K Bi, thxns!");
}
}).define().publish();
console.log('WcThingy' in window)
<template id="TEMPLATE_wc-thingy">
<h1>Shadow DOM here</h1>
<slot></slot>
</template>
<wc-thingy>thingy here</wc-thingy>

最新更新