如何从 parent 向下设置开槽部件的样式

How to style slotted parts from the parent downwards

如何设置已插入 Web 组件的部分的样式?

我的目标是创建 'functional' 组件,这些组件仅根据它们所处的状态(使用 Redux)呈现某些部分。然后将这些组件呈现在容器中。 这个容器知道它可以期待哪种 children 并且应该相应地设置 children 中的部分样式。

一个例子是 posts 的提要,其中所有 posts 都是相同的网络组件,只呈现某些部分。 然后有一个网格提要组件并在网格中呈现这些 post。 另一个按时间顺序排列的提要可能会简单地将 post 呈现在彼此之下。 在这两种情况下, post 本身都不知道它所在的上下文。 我希望容器组件负责 layout/styling.

我有点想要 host-context 的倒数。 使用 host-context,post 组件知道它可以在哪些容器中并相应地设置自己的样式。但我想让我的 post 组件保持纯粹的功能,没有任何样式。 (并且 host-context 没有得到很好的支持)

此代码段展示了我在 my-grid 元素中将 post 的标题设为红色的尝试。但是 none 我的尝试成功了。

customElements.define('my-grid', class extends HTMLElement {
  constructor() {
    super().attachShadow({
        mode: 'open'
      })
      .append(document.getElementById(this.nodeName).content.cloneNode(true));
  }
});
customElements.define('my-post', class extends HTMLElement {
  constructor() {
    super().attachShadow({
        mode: 'open'
      })
      .append(document.getElementById(this.nodeName).content.cloneNode(true));
  }
});
<template id="MY-GRID">
  <style>
:host {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  grid-auto-rows: minmax(auto, 100px);
}

::slotted(my-post) {
  display: contents;
}

/* Attempts at styling the parts withing the slotted posts */
my-post h1,
 ::slotted(my-post) h1 {
  background-color: red;
}

my-post ::part(test),
 ::slotted(my-post) ::part(test) {
  background-color: red;
}

my-post::part(test),
 ::slotted(my-post)::part(test) {
  background-color: red;
}
  </style>
  <slot></slot>
</template>
<template id="MY-POST">
  <h1 part="title">Title</h1>
</template>
<my-grid>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
</my-grid>

您有多个问题

  • 错别字:您将 titletest 混合用于 ::part(x) 参考文献
  • ,所以你可以放弃所有这些尝试
  • (根据上述 link)插槽内容保持在光线中DOM;所以你的元素在光DOM:
<my-grid>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
  <my-post></my-post>
</my-grid>

必须从其容器 设置样式。在本例中是主文档 DOM

所以所有 global 样式需要的是:

  my-post::part(title) {
    background: red;
  }

您可以 <my-grid> 中执行此操作,因为 <my-post> 里面 <my-grid> 淡DOM
<my-grid> 无法为其 slotted 内容设置样式(仅 'outer' 皮肤带有 ::slotted

我添加了额外的样式、插槽和一个嵌套的 <my-post> 元素以使事情变得清晰

<script>
  class GridElements extends HTMLElement {
    constructor() { super().attachShadow({mode: 'open'})
      .append(document.getElementById(this.nodeName).content.cloneNode(true)) }}
  customElements.define('my-grid', class extends GridElements {});
  customElements.define('my-post', class extends GridElements {});
</script>
<template id="MY-GRID">
  <style>
    :host{display:grid;grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)) }
    ::slotted(my-post) { background: green }
  </style>
  <slot></slot>
</template>
<style id="GLOBAL_STYLE!!!">
  body { font: 14px Arial; color: blue }
  my-post::part(title) { background: red }
  my-grid > my-post::part(title) { color: gold }
  my-post > my-post::part(title) { background:lightcoral }
</style>
<template id="MY-POST">
  <h1 part="title"><slot name="title">[Title]</slot></h1>
  <slot>[post body]</slot>
</template>
<my-grid>
  <my-post><span slot="title">One</span></my-post>
  <my-post>Two</my-post>
  <my-post></my-post>
  <my-post>
    <my-post><span slot="title">SUB</span></my-post>
  </my-post>
</my-grid>

::从 my-grid

声明的部分样式

我给 my-grid 灯添加了一个 my-postDOM:

https://jsfiddle.net/CustomElementsExamples/j0nxpmuv/

因此,如果您仍想在主 DOM 中声明内容,但样式来自 my-grid,则必须将元素 移至主DOM my-grid 轻DOM:

connectedCallback(){
  this.shadowRoot.append(...this.children);
}

更新#1

另请参阅 exportparts 以了解跨越 多个 阴影 DOM 边界: