【问题标题】:Getting a custom element's id in its constructor在其构造函数中获取自定义元素的 id
【发布时间】:2020-12-31 19:28:22
【问题描述】:

我正在尝试为网站制作一些可重复使用的标题(多个页面,不必费心复制/粘贴所有内容);在它里面我只有一个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>

然而,当我检查时,我发现&lt;logo-element id="null__logo"&gt;&lt;/logo-element&gt;

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

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

【问题讨论】:

    标签: javascript html dom getattribute


    【解决方案1】:

    你是对的,在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);
      }
    });
    &lt;my-element id="ONE"&gt;Hello World!&lt;/my-element&gt;

    无构造函数

    但是你不需要在你自己的元素中的构造函数(将执行来自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);
      }
    });
    &lt;my-element id="TWO"&gt;Hello World!&lt;/my-element&gt;

    注意事项:

    • 展示了设置元素 HTML 内容的不同用途,您可以混合使用适合您的方式
    • id 是一个默认属性(如标题和名称)并且(默认情况下)有一个 Getter/Setter
    • 您的 logo-element 有效,但仍然是未知元素
    • 文档应该说:你不能使用'this'范围引用之前super()被调用
    • 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);
      }
    });
    &lt;my-element id="THREE"&gt;Hello World!&lt;/my-element&gt;

    【讨论】:

    • 谢谢!我使用 shadow DOM 主要是出于同样的原因(浏览器抱怨在元素尚未初始化时使用 innerHTML);顺便说一句,我离 js 大师还很远,所以你能解释一下你为什么创建一个 slot 元素以及 map() 函数的作用吗?
    • SLOT 是将内容引入 shadowDOM 的主要概念之一。 see this long answer。 Javascripts map 将一个数组转换为另一个数组;在上面的代码中,它将 2 个字符串转换为 2 个 DOM 元素。好的做法是始终在 Google 中使用“MDN”字样进行搜索,这样您才能获得正确/最佳的 JavaScript 文档。边玩边学,这需要时间。
    猜你喜欢
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 2023-03-18
    • 2021-08-18
    • 2013-04-05
    • 1970-01-01
    相关资源
    最近更新 更多