如果没有 `<slot />` 而是影子根,子节点会发生什么
What happens to child nodes if there is no `<slot />`, but a shadow root
考虑这段代码:
//js
class FooBar extends HTMLElement {
constructor(){
super();
}
}
customElements.define('foo-bar', FooBar);
<!-- html -->
<foo-bar>
<h1>Test</h1>
</foo-bar>
这将在浏览器中显示 »Test«。
如果构造函数改为:
constructor () {
super();
this.shadow = this.attachShadow({ mode: 'open' })
}
»Test« 消失,因为现在有影子根。
如果构造函数再改成
constructor () {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this.shadow.appendChild(document.createElement('slot'));
}
»Test« 再次出现,因为现在 <foo-bar>
的所有子节点都有一个默认插槽
但是如果影子根中没有<slot />
,子节点会发生什么。它们仍然出现在 this.children
中,其 style.display
属性 仍然是 ""
。所以它们在 dom 内,但没有呈现,即使你 css 告诉相反?这里究竟发生了什么?
完整的详细说明位于:
<foo-bar>
<h1>Test</h1>
</foo-bar>
H1 是 浅色DOM,
“添加” 到 shadowDOM/root 内容是反映到影子DOM,没动!!!
H1 始终保持明亮DOM :
invisible(在页面中)在lightDOM 对于元素 和 shadowDOM/root,
visible(在页面中)用于自定义元素 without shadowDOM/root
除非您使用 appendChild
明确移动它(或任何 DOM 移动操作)
你说:所以它们在 dom 内,但没有渲染,即使你 CSS 告诉相反?
不,它们 是 渲染的,就像任何普通的 DOM 元素一样。只是不再可见了。
您可以通过在 lightDOM 中包含一个 SCRIPT 标签来进行测试。它会 render 并执行!
在下面的代码片段中
您引用 lightDOM 和 this.querySelector("span").innerHTML="weird";
但是用 this.shadowRoot.querySelector("span").innerHTML="weird";
引用 shadowDOM
不有效吗,因为DIV(里面有SPAN)是黑盒 在
<template id="MY-ELEMENT">
<style>
:host {
display: inline-block;
font-family: Arial;
}
::slotted(div){
color:blue;
}
::slotted(span){
color:gold; /* alas, you can style the 'box', not elements inside */
}
</style>
<h3><slot></slot></h3>
</template>
<style>
span {
background:lightcoral; /* from global/host CSS, style slotted content lightDOM */
}
</style>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
super().attachShadow({mode: 'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
}
});
</script>
<my-element>
<div>Hello <span>Component</span> World!</div>
</my-element>
在 F12 开发工具中检查组件:
Chrome & Firefox:
DIV 不在 shadowDOM/root 中,在光线下不可见DOM
所有 elements/styles 将始终 反映 到 shadowDOM/root
点击'reveal'带你走向光明DOM
So to shadowDOM, slotted content is a black-box of elements & styles;
reflected from lightDOM
that is why ::slotted
can only style the box, and not what is inside.
注意:在F12控制台编辑DIV,你会立即看到变化反映到阴影DOM
插槽和灯DOM 是实时连接
通过更改 <slot name=...>
,您可以进行以前需要更多编码的交互(想想路线、选项卡、答案)(还记得那些 jQuery show/hide 天吗?)
<template id="MY-ELEMENT">
Custom Element SLOTs are:
<slot name=answer></slot>
</template>
<style>
img { /* style all IMGs in lightDOM */
max-width: 100vw;
max-height: 70vh;
}
</style>
<script>
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.onclick = (evt) => {
const answer = evt.composedPath()[0].innerText; // button label
this.shadowRoot.querySelector('slot').name = answer;
this.children[0].slot = answer;//include lightDOM buttons again
}
}
});
</script>
<my-element>
<span slot=answer><button>Cool</button><button><b>Awesome</b></button><button>Great</button></span>
<div slot=Cool><img src="https://i.imgur.com/VUOujQT.jpg"></div>
<span slot=Awesome> <h3>SUPER!</h3></span>
<div slot=Awesome><img src="https://i.imgur.com/y95Jq5x.jpg"></div>
<div slot=Great><img src="https://i.imgur.com/gUFZNQH.jpg"></div>
</my-element>
更多与 SLOT 相关的答案可以通过 Whosebug 搜索找到:Custom Elements SLOTs
考虑这段代码:
//js
class FooBar extends HTMLElement {
constructor(){
super();
}
}
customElements.define('foo-bar', FooBar);
<!-- html -->
<foo-bar>
<h1>Test</h1>
</foo-bar>
这将在浏览器中显示 »Test«。
如果构造函数改为:
constructor () {
super();
this.shadow = this.attachShadow({ mode: 'open' })
}
»Test« 消失,因为现在有影子根。
如果构造函数再改成
constructor () {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this.shadow.appendChild(document.createElement('slot'));
}
»Test« 再次出现,因为现在 <foo-bar>
但是如果影子根中没有<slot />
,子节点会发生什么。它们仍然出现在 this.children
中,其 style.display
属性 仍然是 ""
。所以它们在 dom 内,但没有呈现,即使你 css 告诉相反?这里究竟发生了什么?
完整的详细说明位于:
<foo-bar>
<h1>Test</h1>
</foo-bar>
H1 是 浅色DOM,
“添加” 到 shadowDOM/root
H1 始终保持明亮DOM :
invisible(在页面中)在lightDOM 对于元素 和 shadowDOM/root,
visible(在页面中)用于自定义元素 without shadowDOM/root
除非您使用
appendChild
明确移动它(或任何 DOM 移动操作)
你说:所以它们在 dom 内,但没有渲染,即使你 CSS 告诉相反?
不,它们 是 渲染的,就像任何普通的 DOM 元素一样。只是不再可见了。
您可以通过在 lightDOM 中包含一个 SCRIPT 标签来进行测试。它会 render 并执行!
在下面的代码片段中
您引用 lightDOM 和 this.querySelector("span").innerHTML="weird";
但是用 this.shadowRoot.querySelector("span").innerHTML="weird";
不有效吗,因为DIV(里面有SPAN)是黑盒 在
<template id="MY-ELEMENT">
<style>
:host {
display: inline-block;
font-family: Arial;
}
::slotted(div){
color:blue;
}
::slotted(span){
color:gold; /* alas, you can style the 'box', not elements inside */
}
</style>
<h3><slot></slot></h3>
</template>
<style>
span {
background:lightcoral; /* from global/host CSS, style slotted content lightDOM */
}
</style>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
super().attachShadow({mode: 'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
}
});
</script>
<my-element>
<div>Hello <span>Component</span> World!</div>
</my-element>
在 F12 开发工具中检查组件:
Chrome & Firefox:
DIV 不在 shadowDOM/root 中,在光线下不可见DOM
所有 elements/styles 将始终 反映 到 shadowDOM/root
点击'reveal'带你走向光明DOM
So to shadowDOM, slotted content is a black-box of elements & styles;
reflected from lightDOM
that is why::slotted
can only style the box, and not what is inside.
注意:在F12控制台编辑DIV,你会立即看到变化反映到阴影DOM
插槽和灯DOM 是实时连接
通过更改 <slot name=...>
,您可以进行以前需要更多编码的交互(想想路线、选项卡、答案)(还记得那些 jQuery show/hide 天吗?)
<template id="MY-ELEMENT">
Custom Element SLOTs are:
<slot name=answer></slot>
</template>
<style>
img { /* style all IMGs in lightDOM */
max-width: 100vw;
max-height: 70vh;
}
</style>
<script>
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.onclick = (evt) => {
const answer = evt.composedPath()[0].innerText; // button label
this.shadowRoot.querySelector('slot').name = answer;
this.children[0].slot = answer;//include lightDOM buttons again
}
}
});
</script>
<my-element>
<span slot=answer><button>Cool</button><button><b>Awesome</b></button><button>Great</button></span>
<div slot=Cool><img src="https://i.imgur.com/VUOujQT.jpg"></div>
<span slot=Awesome> <h3>SUPER!</h3></span>
<div slot=Awesome><img src="https://i.imgur.com/y95Jq5x.jpg"></div>
<div slot=Great><img src="https://i.imgur.com/gUFZNQH.jpg"></div>
</my-element>
更多与 SLOT 相关的答案可以通过 Whosebug 搜索找到:Custom Elements SLOTs