slot
制作一个可重用的 web 组件很好,但是到目前为止它有一个限制。我面临的是风格问题。您只是无法在组件内部定义样式,即使您知道注入内容的结构是什么。
从我在 github 的帖子中找到的详细信息
我编写了一个组件,并尝试slot
从外部注入内容并尝试为组件影子根中的特定内容添加样式。
演示
HTML 文件
<my-navbar>
<ul>
<li>link1</li>
<li>link2</li>
<li>link3</li>
</ul>
</my-navbar>
JS文件
customElements.define('my-navbar', class extends HTMLElement {
constructor () {
super();
const sr = this.attachShadow({ mode: 'open' });
sr.innerHTML = `
<style>
/*worked*/
::slotted(ul)
{
color:green;
}
/*
Suppose I know the outside content is "ul li", and I directly define the
style after they injected into component's slot. However, it just doesn't
work because the slotted selector is just a compound selector. It can only
affect the first layer 'ul'. It can't affect the child dom 'li' */
::slotted(ul li)
{
color:red;
}
</style>
<slot></slot>
`;
}
});
但是,它不能直接工作,因为您不能为::slot(simple_selector) 原因使用复杂的选择器
我找到了一个间接的解决方案,那就是将外部内容重新附加到组件影子根内的插槽中。 演示
HTML 文件
<my-navbar>
<!--a dom defined a slot property-->
<ul slot='t'>
<li>link1</li>
<li>link2</li>
<li>link3</li>
</ul>
<!--A dom not define slot property-->
<span>1234</span>
</my-navbar>
JS文件
customElements.define('my-navbar', class extends HTMLElement {
constructor () {
super();
const sr = this.attachShadow({ mode: 'open' });
sr.innerHTML = `
<style>
ul li
{
color:red;
}
</style>
<slot name='t'></slot>
<slot ></slot>
`;
// Do something later...
setTimeout(this.appendOutsideSlotContentIntoInsideSlot.bind(this), 1000)
}
appendOutsideSlotContentIntoInsideSlot()
{
// Insert outside dom element which has define slot property into the specify slot inside the shadow root
debugger;
for (let objIndex=0;objIndex<this.children.length;)
{
var obj=this.children[objIndex];
if(obj.slot){
var slot=this.shadowRoot.querySelector('slot[name='+obj.slot+']');
if(slot)
{
slot.appendChild(obj);
continue;
}
}
objIndex++;
}
// Insert the rest dom which has not define slot property values into the anonymous slot
var defaultSlot=Array.prototype.slice.call(this.shadowRoot.querySelectorAll('slot')).filter(function(el){ return !el.name})[0];
debugger;
if(defaultSlot)
{
while (this.children.length>0)
{
defaultSlot.appendChild(this.children[0])
}
}
}
});
好吧,它适用于定义了 slot 属性的内容,但不适用于没有 slot 属性的内容。