我遇到了使用自定义元素的问题。
错误: Uncaught DOMException: Failed to construct 'CustomElement': The result must not have children
'use strict';
class TestCard extends HTMLDivElement {
constructor() {
super();
this.headerNode = document.createElement('div');
this.bodyNode = document.createElement('div');
this.headerNode.className = 'card__header';
this.bodyNode.className = 'card__body';
this.appendChild(this.headerNode);
this.appendChild(this.bodyNode);
}
connectedCallback() {
this.classList.add('card');
}
static get observedAttributes() {
return ['data-header', 'data-body'];
}
attributeChangedCallback(attrName, oldValue, newValue) {
if (newValue !== oldValue) {
this[attrName.replace('data-', '')] = newValue;
}
}
set header(value) {
this.headerNode.textContent = value;
this.setAttribute('data-header', value);
}
set body(value) {
this.bodyNode.innerHTML = value;
this.setAttribute('data-body', value);
}
}
customElements.define('test-card', TestCard, {
extends: 'div'
});
<div is="test-card" data-header="Title" data-body="Content"></div>
创建WebComponent :
var cardNode = document.createElement('div');
cardNode.setAttribute('is', 'test-card');
cardNode.header = header;
cardNode.body = body;
发布于 2022-04-01 15:09:31
在自定义元素的构造函数中,有些东西是不允许的。有关此选项的更多信息,请查看我对一个类似问题的老回答)。
除其他外,其中包括:
class
,它被认为是由使用组件的人控制的)要实现您想要做的事情,请使用阴影DOM:
class TestComp extends HTMLElement {
headerNode = document.createElement('div');
bodyNode = document.createElement('div');
constructor() {
super();
this.attachShadow({mode: 'open'});
this.headerNode.className = 'card__header';
this.bodyNode.className = 'card__body';
this.bodyNode.part = 'body';
this.shadowRoot.append(this.headerNode, this.bodyNode);
}
connectedCallback() {
this.classList.add('card');
}
static get observedAttributes() {
return ['data-header', 'data-body'];
}
attributeChangedCallback(attrName, oldValue, newValue) {
if (newValue !== oldValue) {
this[attrName.replace('data-', '')] = newValue;
}
}
set header(value) {
this.headerNode.textContent = value;
this.dataset.header = value;
}
set body(value) {
this.bodyNode.innerHTML = value;
this.dataset.body = value;
}
}
customElements.define('test-comp', TestComp);
let newTestComp = new TestComp();
newTestComp.header = 'FOOO';
newTestComp.body = '<ul><li><i>BA</i><b>AA</b>R</ul>';
document.body.append(newTestComp);
test-comp::part(body) { color: green; }
<test-comp data-header="Titre de ma carte" data-body="<h1>Test</h1>"></test-comp>
请注意,使用影子DOM意味着外部样式不会影响阴影树中元素的样式。要将样式应用于这些样式,请在构造函数中创建一个<style>
元素,将它的textContent
属性设置为您的样式,并将其附加到阴影DOM中其他元素的旁边。
与使用style
元素不同,您还可以使用可构造样式表。您可能需要一个聚脂填充,因为到目前为止,基于铬的浏览器是唯一支持它的浏览器,但在其他浏览器中正在提供支持。已经有一段时间了:打开新选项卡,导航到about:config
,然后将layout.css.constructable-stylesheets.enabled
设置为true
)。
要允许从外部CSS对组件内部进行样式化,可以使用阴影DOM中的part="name"
属性从外部样式化哪些元素,然后使用CSS中的::part(name)
选择器对其进行样式设置。将其添加到代码示例中。
发布于 2022-04-01 14:42:43
关于你提到的错误,我不能说,但还有一件事你应该改变。
在您的代码中重新排序这些事情
constructor() {
super();
this.classList.add('card');
this.headerNode = this.getElementsByClassName('card__header')[0];
this.bodyNode = this.getElementsByClassName('card__body')[0];
this.innerHTML = `<div class="card__header"></div>
<div class="card__body"></div>`;
}
至
constructor() {
super();
this.classList.add('card');
this.innerHTML = `<div class="card__header"></div>
<div class="card__body"></div>`;
this.headerNode = this.getElementsByClassName('card__header')[0];
this.bodyNode = this.getElementsByClassName('card__body')[0];
}
因为您在后面的代码中添加了类card__header
和card__body
的元素,所以您试图访问它,这就是为什么this.headerNode
是undefined
的原因。
发布于 2022-04-01 15:58:37
正如我在“康奈尔”中所评论的,他以前的回答。
您必须了解网络组件生命周期:https://andyogo.github.io/custom-element-reactions-diagram/
运行new TestComp()
或document.createElement("test-comp")
时
没有DOM元素,只有constructor
运行,并告诉您,
您不能向它添加 DOM (子级) (nothing)。只有在connectedCallback
中才能使用现有的 DOM,在之后或中的任何--您的<test-comp>
可能E 217
还不存在;参见:在connectedCallback中等待元素升级: FireFox和铬的差异
请优化构造函数,
任何显示this.shadowRoot
在constructor
中的博客或答案都应该被烧毁。
constructor() {
super() // sets AND returns "this" scope
.attachShadow({mode:'open'}) // sets AND returns shadowRoot
.append(
this.headerNode = document.createElement('div'),
this.bodyNode = document.createElement('div')
);
this.headerNode.className = 'card__header';
this.bodyNode.className = 'card__body';
}
https://stackoverflow.com/questions/71708470
复制相似问题