HTML web component 没有使用 shadow DOM 样式

HTML web component does not use shadow DOM style

我创建了一个 vanilla web 组件或 HTML 元素。它只显示两个链接。

为了封装这个东西,我使用了 shadow DOM。但是它似乎没有被封装。在 DOM 树中,它位于 #shadow-root 中,这很好。

为什么 Web 组件使用全局样式而不是我在模板中为我的 Web 组件提供的样式?

文本是红色的,我希望它是绿色的。

class MyEl extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: "open" });
  }

  connectedCallback() {
    const template = `
      <style>
        a {
          color: green;
        }
      </style>
      <slot></slot>`;
    this.shadow.innerHTML = template;
  }
}

window.customElements.define("my-el", MyEl);
a {
  color: red
}
  <my-el>
    <a href="example.com">Item1</a>
    <a href="example.com">Item2</a>
  </my-el>

观察这一行,你必须 move/copy 个元素来遮蔽例如:

this.shadow.innerHTML = this.innerHTML + template;

我添加这个是为了证明只有内联样式会应用于阴影 dom 元素..所以在 SD 中复制的链接正在使用您的样式:)

所以红色将是GLOBAL绿色将是SHADOW个元素

class MyEl extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.shadow = this.attachShadow({ mode: "open" });
    const template = `
      <style>
        a {
          color: green;
        }
      </style>
      <slot></slot>`;
    this.shadow.innerHTML = this.innerHTML + template;
  }
}

window.customElements.define("my-el", MyEl);
a {
  color: red
}
<my-el>
    <a href="example.com">Item1</a>
    <a href="example.com">Item2</a>
  </my-el>

完整、详细的解释在:

TL;DR

您的链接很清晰DOM,因此其样式由其 DOM(在您的代码中,文档 DOM)
将节点从 lightDOM 移动到 shadowDOM 是一个“解决方案”;但是你当时没有使用插槽。

仅供参考,您的代码可以压缩为:

class MyEl extends HTMLElement {
  constructor() {
    super().attachShadow({ mode: "open" })
           .innerHTML = `<style>a{color:green}</style><slot></slot>`;

  }
}

window.customElements.define("my-el", MyEl);

更多与 SLOT 相关的答案可以通过 Whosebug 搜索找到:Custom Elements SLOTs

虽然这个问题已经有了公认的答案,但对于大多数用例来说,将插槽的子级移动到 shadowRoot 是不可取的。

您可能想要做的是使用 ::slotted() 选择器。

请记住,通过 ::slotted() 选择器应用于插槽子项的样式仅作为“默认”样式,仍然可以使用 light DOM.[=19 中的样式覆盖=]

例如,检查您的代码段的这个编辑版本:

如您所见,这次 my-el 尝试同时应用颜色和 text-decoration 样式来将 (<a>) 子级锚定在它的任何插槽中。

但是,在灯光 dom 中,我们有一个覆盖颜色的 a.special 选择器,因此 <a class="special"> 将是红色,而不是绿色

class MyEl extends HTMLElement {
  constructor() {
    super();
    this.shadow = this.attachShadow({ mode: "open" });
  }

  connectedCallback() {
    const template = `
      <style>
        ::slotted(a) {
          color: green;
          text-decoration: none;
        }
      </style>
      <slot></slot>`;
    this.shadow.innerHTML = template;
  }
}

window.customElements.define("my-el", MyEl);
a.special {
  color: red
}
  <my-el>
    <a href="example.com">Item1</a>
    <a class="special" href="example.com">Item2</a>
  </my-el>