通过Shadow DOM(v1)示例in this tutorial,它定义了一个Web组件(选项卡),其中每个选项卡都对应一个命名的默认插槽:
<fancy-tabs>
<button slot="title">Title</button>
<button slot="title" selected>Title 2</button>
<button slot="title">Title 3</button>
<section>content panel 1</section>
<section>content panel 2</section>
<section>content panel 3</section>
</fancy-tabs>
它将导致:
<fancy-tabs>
#shadow-root
<div id="tabs">
<slot id="tabsSlot" name="title">
<button slot="title">Title</button>
<button slot="title" selected>Title 2</button>
<button slot="title">Title 3</button>
</slot>
</div>
<div id="panels">
<slot id="panelsSlot">
<section>content panel 1</section>
<section>content panel 2</section>
<section>content panel 3</section>
</slot>
</div>
</fancy-tabs>
为了保留现有的API,我想创建一个与此类似的组件,但是我可以在其中创建每个Tab作为其自己的Custom Element。因此,API类似于:
<fancy-tabs>
<fancy-tab>
<button slot="title">Title</button>
<section>content panel 1</section>
</fancy-tab>
<fancy-tab>
<button slot="title" selected>Title 2</button>
<section>content panel 2</section>
<fancy-tab>
<fancy-tab>
<button slot="title" selected>Title 3</button>
<section>content panel 3</section>
<fancy-tab>
</fancy-tabs>
但是将其渲染为与上述类似的Shadow DOM。
换句话说,我想要的是一个中间元素,例如
<fancy-tab>
,同时仍控制其下面的slot元素。我尝试将<fancy-tab>
创建为带有开放shadowRoot的CE,作为没有shadowRoot的CE,并且根本没有将其定义为自定义元素。有办法吗? 还是插槽必须位于Light DOM的第一个子节点上?
最佳答案
具有slot
属性的元素必须是Light DOM的第一个子元素。
因此,如果您想保留第三段代码的结构,可以使用nested custom elements,每个都有影子DOM。<fancy-tabs>
组件将抓取<fancy-tab>
。<fancy-tab>
组件将获取内容。
实际上,创建“选项卡”组件甚至不必定义影子DOM的子组件(但是您当然可以满足自定义需求)。
这是一个最小的<fancy-tabs>
自定义元素示例:
customElements.define( 'fancy-tabs', class extends HTMLElement
{
constructor()
{
super()
this.btns = this.querySelectorAll( 'button ')
this.addEventListener( 'click', this )
this.querySelector( 'button[selected]' ).focus()
}
handleEvent( ev )
{
this.btns.forEach( b =>
{
if ( b === ev.target )
b.setAttribute( 'selected', true )
else
b.removeAttribute( 'selected' )
} )
}
} )
fancy-tabs {
position: relative ;
}
fancy-tab > button {
border: none ;
}
fancy-tab > section {
background: #eee ;
display: none ;
position: absolute ; left: 0 ; top: 20px ;
width: 300px ; height: 75px ;
}
fancy-tab > button[selected] + section {
display: inline-block ;
}
<fancy-tabs>
<fancy-tab>
<button>Title 1</button>
<section>content panel 1</section>
</fancy-tab>
<fancy-tab>
<button selected>Title 2</button>
<section>content panel 2</section>
</fancy-tab>
<fancy-tab>
<button>Title 3</button>
<section>content panel 3</section>
</fancy-tab>
</fancy-tabs>
关于web-component - 如果我之间有一个中间元素,是否可以插入Shadow DOM内容?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42637052/