微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从父级向下设置开槽零件的样式 ::part 样式声明自 my-grid更新 #1

如何解决如何从父级向下设置开槽零件的样式 ::part 样式声明自 my-grid更新 #1

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

我的目标是创建“功能性”组件,这些组件仅根据它们所处的状态(使用 Redux)呈现某些部分。然后将这些组件呈现在容器中。 这个容器知道它可以期待什么样的孩子,并应该相应地设计孩子的部分。

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

我有点想要主机上下文的反转。 使用宿主上下文,post 组件知道它可以在哪个容器中,并相应地设置自己的样式。但我想保持我的帖子组件纯粹的功能,没有任何样式。 (并且主机上下文没有得到很好的支持

代码显示了我尝试将位于 my-grid 元素中的帖子标题设为红色的尝试。但我的尝试都没有奏效。

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>

解决方法

您遇到了多个问题

  • 错别字:您在 title 引用中混用了 test::part(x)
  • ::slotted is a very simple selector,因此您可以放弃所有这些尝试
  • (根据上面的链接)插入的内容保留在 lightDOM 中;所以你在 lightDOM 中的元素:
<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

所以所有需要的全局样式是:

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

您可以<my-grid>中这样做,因为<my-post> <my-grid> lightDOM
<my-grid> 无法设置其slotted 内容的样式(仅带有 ::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>

::part 样式声明自 my-grid

我向 my-post lightDOM 添加了一个 my-grid

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

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

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

更新 #1

另请参阅 exportparts 以跨越多个 shadowDOM 边界:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。