在其构造函数中获取自定义元素的 ID

Getting a custom element's id in its constructor

我正在尝试为网站制作一些可重复使用的 header(多个页面,不能为 copy/paste 一切烦恼);在里面我只有一个 logo-element 元素(也是自定义的),我想让它的 id 等于 header 加上一个 __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 不是必需的;您可以在没有
  • 的情况下创建自定义元素

无阴影DOM

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>