首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >未能构建CustomElement

未能构建CustomElement
EN

Stack Overflow用户
提问于 2022-04-01 14:23:22
回答 3查看 282关注 0票数 1

我遇到了使用自定义元素的问题。

错误: Uncaught DOMException: Failed to construct 'CustomElement': The result must not have children

代码语言:javascript
运行
复制
'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'
});
代码语言:javascript
运行
复制
<div is="test-card" data-header="Title" data-body="Content"></div>

创建WebComponent :

代码语言:javascript
运行
复制
var cardNode = document.createElement('div');
cardNode.setAttribute('is', 'test-card');
cardNode.header = header;
cardNode.body = body;
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-04-01 15:09:31

在自定义元素的构造函数中,有些东西是不允许的。有关此选项的更多信息,请查看我对一个类似问题的老回答)。

除其他外,其中包括:

  • 访问属性(特别是写入属性,这包括class,它被认为是由使用组件的人控制的)
  • 访问子 (既不读也不写)
    • ,除非在组件的阴影树中这样做。

要实现您想要做的事情,请使用阴影DOM:

代码语言:javascript
运行
复制
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);
代码语言:javascript
运行
复制
test-comp::part(body) { color: green; }
代码语言:javascript
运行
复制
<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)选择器对其进行样式设置。将其添加到代码示例中。

票数 3
EN

Stack Overflow用户

发布于 2022-04-01 14:42:43

关于你提到的错误,我不能说,但还有一件事你应该改变。

在您的代码中重新排序这些事情

代码语言:javascript
运行
复制
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>`;
  }

代码语言:javascript
运行
复制
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__headercard__body的元素,所以您试图访问它,这就是为什么this.headerNodeundefined的原因。

票数 0
EN

Stack Overflow用户

发布于 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.shadowRootconstructor中的博客或答案都应该被烧毁。

代码语言:javascript
运行
复制
  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';
  }
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71708470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档