在其构造函数中获取自定义元素的 id 没有构造函数注意事项:没有shadowDOM

问题描述

我正在尝试为网站制作一些可重复使用的标题(多个页面,无法复制/粘贴所有内容);在它里面我只有一个 logo-element 元素(也是自定义的),我想让它的 id 等于标题加上一个 __logo 后缀。

这是 javascript:

class TopBar extends HTMLElement {
    constructor() {
        super();

        this.attachShadow({ mode: "open" });

        let logoElement = document.createElement("logo-element");
        logoElement.setAttribute("id",`${ this.getAttribute("id") }__logo`);

        this.shadowRoot.append(logoElement); 
    }
}

customElements.define('top-bar-element',TopBar);

这是 HTML:

<top-bar-element id="top-bar"></top-bar-element>

然而,当我检查时,我发现 <logo-element id="null__logo"></logo-element>

我猜是因为浏览器只在元素创建后才设置属性

还有其他解释吗?有解决方法吗?

解决方法

你是对的,在 constructor 阶段元素只在内存中,不能访问 DOM

因此您必须在 connectedCallback 中执行此操作:

customElements.define('my-element',class extends HTMLElement {
  constructor() {
    let content = ["slot","logo-element"].map(x=>document.createElement(x));
    super() // docs are wrong,super doesn't have to be first
      .attachShadow({mode: "open" })
      .append( ...content );
  }
  connectedCallback() {
    this  
      .shadowRoot
      .querySelector("logo-element")
      .id = this.id + "__logo";

    console.log(this.shadowRoot.innerHTML);
  }
});
<my-element id="ONE">Hello World!</my-element>

没有构造函数

但是您不需要自己元素中的构造函数(将执行 HTMLElement 中的默认构造函数)

customElements.define('my-element',class extends HTMLElement {
  connectedCallback() {
    this.attachShadow({mode: "open"}).innerHTML = `<slot></slot>`;
    let el = this.shadowRoot.appendChild(document.createElement("logo-element"));
    el.id = this.id + "__logo";
    console.log(this.shadowRoot.innerHTML);
  }
});
<my-element id="TWO">Hello World!</my-element>

注意事项:

  • 展示了设置元素 HTML 内容的不同用途,您可以混合使用适合您的内容
  • id 是一个默认属性(如标题和名称)并且(默认情况下)有一个 Getter/Setter
  • 您的 logo-element 有效,但仍然是未知元素
  • 文档应该说:在调用 super() 之前,您不能使用“this”范围引用
  • shadowDOM 不是必需的;您可以在没有
  • 的情况下创建自定义元素

没有shadowDOM

customElements.define('my-element',class extends HTMLElement {
  connectedCallback() {
    this.innerHTML = `<logo-element id="${this.id}__logo">${this.innerHTML}</logo-element>`;
    console.log(this.innerHTML);
  }
});
<my-element id="THREE">Hello World!</my-element>