【发布时间】:2020-12-23 10:53:55
【问题描述】:
是否可以自动或以编程方式插入嵌套的 Web 组件或特定类型的元素,而无需为其指定 slot 属性?
考虑这样的结构:
<parent-element>
<child-element>Child 1</child-element>
<child-element>Child 2</child-element>
<p>Content</p>
</parent-element>
<parent-element> 具有这样的 Shadow DOM:
<div id="child-elements">
<slot name="child-elements">
<child-element>Default child</child-element>
</slot>
</div>
<div id="content">
<slot></slot>
</div>
预期结果是:
<parent-element>
<#shadow-root>
<div id="child-elements">
<slot name="child-elements">
<child-element>Child 1</child-element>
<child-element>Child 2</child-element>
</slot>
</div>
<div id="content">
<slot>
<p>Content</p>
</slot>
</div>
</parent-element>
换句话说,我想强制 <child-element>s 只允许在 <parent-element> 内使用,类似于 <td> 元素只允许在 <tr> 元素内使用。我希望它们被放置在<slot name="child-elements"> 元素中。必须为它们中的每一个指定 slot 属性以将它们放置在 <parent-element> 的特定插槽中似乎是多余的。
同时,<parent-element> 中的其余内容应自动插入到第二个 <slot> 元素中。
我在注册父元素时首先搜索了一种方法来定义它,尽管CustomElementRegistry.define() 目前只支持extends 作为选项。
然后我想,也许有一个功能允许手动插入元素,即类似childElement.slot('child-elements'),但似乎不存在。
然后我尝试在父元素的构造函数中以编程方式实现这一点,如下所示:
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
const childElements = this.getElementsByTagName('child-element');
const childElementSlot = this.shadowRoot.querySelector('[name="child-elements"]');
for (let i = 0; i < childElements.length; i++) {
childElementSlot.appendChild(childElements[i]);
}
}
虽然这不会将子元素移动到<slot name="child-elements">,但它们仍然会被插入到第二个<slot> 元素中。
【问题讨论】:
-
我认为这可能是一个很好的问题,但就目前的形式而言,您想要实现的目标以及到目前为止您已经设法实现的目标有点令人困惑。为了清楚起见,请您编辑/重写您的问题 - 我喜欢 WebComponents,我想为您提供帮助。
-
@Rounin,想
slotchange活动为您解答... -
@Rounin 我已经扩展了我的答案,以澄清预期结果是什么以及到目前为止我已经尝试过什么。
-
@Danny'365CSI'Engelman 据我所知,
slotchange事件仅在添加或删除元素后在<slot>元素上触发,但我没有看看这如何帮助我将它们放入正确的插槽中。 -
我猜你的意思是
childEements[i]而不是tabs[i]???在这种情况下,您不再使用SLOT技术,因为您现在将 移动 lightDOM 内容到 shadowDOM
标签: html web-component shadow-dom custom-element html-templates