【问题标题】:duplicated named slot inside shadow dom not working影子dom内重复的命名槽不起作用
【发布时间】:2021-06-03 20:23:46
【问题描述】:

我有一个看起来像这样的自定义元素:

class RepeatMe extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });

        let slot = document.createElement('slot');
        slot.setAttribute('name', 'bar');
        this.shadowRoot.append(slot);

        slot = document.createElement('slot');
        slot.setAttribute('name', 'content');
        this.shadowRoot.append(slot);

        slot = document.createElement('slot');
        slot.setAttribute('name', 'bar');
        this.shadowRoot.append(slot);
    }
}

window.customElements.define('repeat-me', RepeatMe);

我的使用方法如下:

<repeat-me>
    <div slot="bar">I'm a bar</div>
    <div slot="content">I'm some content</div>
</repeat-me>

我想在shadow dom中重复槽bar(因为开头和结尾的内容相同),但我得到的是只有第一个槽被渲染,第二个是空的。我试图用影子 dom 插槽做的事情是否可行,或者你知道一些方法来实现这样的事情吗?

【问题讨论】:

    标签: javascript web-component shadow-dom custom-element slot


    【解决方案1】:

    不,SLOT 是独一无二的
    并且可以将多个 lightDOM 元素插入到同一个 SLOT 中

    将 SLOT 视为您的邮箱;您希望您的邮件始终复制到另一个邮箱吗?

    如果您有此要求,则需要一个过滤器来复制电子邮件(或插槽内容)

    使用 WebComponents 有 2 个复制选项:

    1. &lt;span slot="bar"&gt; 克隆到 shadowRoot 内的其他(非插槽)DOM 元素

    2. 克隆到新的 lightDOM 元素 &lt;span slot="duplicate_bar1"&gt; 以获取新的插槽内容

    下面的代码具有slotchange&lt;span slot="bar"&gt; 上发生的事件的两个选项(插槽中的新内容)

    1. slotchange 上,槽内容被克隆到class="duplicate_bar" (let dups = ...)

    2. slotchange 创建新的 lightDOM 元素 (let dupslots = ...)

    请注意,只有方法 2. 使用 &lt;slot&gt; 功能,您可以使用 :slotted 样式

    此代码仅复制内容;它不会清理已删除的 SLOT 内容。

    <my-element>
      <span slot="bar"> ONE </span>
      <span slot="bar"> TWO </span>
      <span slot="content"> content </span>
    </my-element>
    <template id="MY-ELEMENT">
      <style>
        ::slotted(*) { background: lightgreen }
      </style>
      slot bar: <slot name="bar"></slot>
      <br> slot: content: <slot name="content"></slot>
      <br>Duplicate in SPAN: <span class="duplicate_bar"></span>
      <br>Duplicate in B:<b class="duplicate_bar"></b>
      <br>duplicate_bar1:<slot name="duplicate_bar1"></slot>
      <br>duplicate_bar2:<slot name="duplicate_bar2"></slot>
    </template>
    <script>
      customElements.define('my-element', class extends HTMLElement {
        constructor() {
          let template = id => document.getElementById(id).content.cloneNode(true);
          super().attachShadow({mode: 'open'}).append(template(this.nodeName));
          let slotname = "bar";
          let slot = this.shadowRoot.querySelector(`[name="${slotname}"]`);
          slot.addEventListener("slotchange", (evt) => {
            let assigned = slot.assignedNodes();
            let dups = [...this.shadowRoot.querySelectorAll(".duplicate_" + slotname)];
            let dupslots = [...this.shadowRoot.querySelectorAll(`slot[name*="duplicate_bar"]`)];
            assigned.forEach(node => {
              dups.forEach(el => el.append(node.cloneNode(true)));
              dupslots.forEach(duplicateslot => {
                let newNode = node.cloneNode(true);
                newNode.slot = duplicateslot.name; // set BEFORE adding to DOM! otherwise 'bar' slotchange Events triggers on it
                this.append(newNode);
              })
            });
          });
        }
      });
    </script>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多