将带有插槽的影子 dom 的子级移出 Web 组件

Move child of shadow dom with slots out of the web component

我正在尝试将 Web 组件的影子 dom 的子项移到它外面,如果该子项没有插槽,我已经能够做到这一点。

让我举个例子。我有以下 2 个网络组件:

customElements.define('a-child', class extends HTMLElement {
    constructor() {
        super()
        this.attachShadow({mode: 'open'})
        this.shadowRoot.innerHTML = `
            <slot></slot>
        `
    }
})

customElements.define('a-parent', class extends HTMLElement {
    constructor() {
        super()
        this.attachShadow({mode: 'open'})
        this.shadowRoot.innerHTML = `
            <slot name="outside"></slot>
            <a-child id=child>
                <div>
                    <slot name="inside"></slot>
              </div>
            </a-child>
        `
    }
    
    move() {
        const child = this.shadowRoot.getElementById('child')
        document.body.append(child)
    }
})

如果我有以下 HTML,我就得到了我想要的:即使插槽 inside 位于影子 DOM 中的 a-child 组件内,来自 a-parent,显示正确。

<a-parent id="parent">
    <div slot="outside">outside</div>
    <div slot="inside">inside</div>
</a-parent>

如果我 运行 来自 ID 为 parent 的元素的方法 movea-child 元素被移动到正文,我期待看到 div 正文中带有文本 inside,但它并没有发生。插槽似乎只有在其网络组件内时才有效。

我的问题是,是否可以将包含插槽的 Shadow DOM 的子项移动到其 Web 组件父项之外?

你是对的。槽仅在它们位于其封闭的 Web 组件内时才起作用。换句话说,插槽应该物理存在于 Web 组件节点下的 DOM 树中。

此外,可以移动 Shadow DOM 的子项,但如果它们包含插槽,则无法移动。它会静静地失败而不会出现任何错误。

这是令人讨厌的原因之一。 for similar question. Also, this twitter thread 包含更多相关信息。总之,您需要将插槽元素移到组件外部,以实现完美的堆叠上下文,以创建对话框、菜单、下拉列表等组件