phi*_*ipp 6 javascript web-component custom-element
考虑这个代码:
//js
class FooBar extends HTMLElement {
constructor(){
super();
}
}
customElements.define('foo-bar', FooBar);
<!-- html -->
<foo-bar>
<h1>Test</h1>
</foo-bar>
Run Code Online (Sandbox Code Playgroud)
这将在浏览器中显示»Test«。
如果构造函数改为:
constructor () {
super();
this.shadow = this.attachShadow({ mode: 'open' })
}
Run Code Online (Sandbox Code Playgroud)
»Test« 消失了,因为现在有一个影子根。
如果构造函数进一步更改为
constructor () {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this.shadow.appendChild(document.createElement('slot'));
}
Run Code Online (Sandbox Code Playgroud)
»Test« 再次出现,因为现在所有子节点都有一个默认插槽 <foo-bar>
但是如果<slot />影子根中没有子节点会发生什么。他们仍然出现在里面this.children并且它的style.display财产仍然存在""。所以他们在 dom 内,但没有被渲染,即使你 thr css 告诉相反?这里究竟发生了什么?
完整的详细解释位于::: slotted CSS 选择器用于在shadowDOM 槽中嵌套子项
<foo-bar>
<h1>Test</h1>
</foo-bar>
Run Code Online (Sandbox Code Playgroud)
H1是lightDOM,
“添加”到shadowDOM/root <SLOT>内容被反射到shadowDOM,而不是移动!
H1 始终保留在 lightDOM 中:
对于具有ShadowDOM/root 的元素,在lightDOM中不可见(在页面中) ,
对于没有ShadowDOM/root 的自定义元素可见(在页面中)
appendChild除非你使用(或任何 DOM 移动操作)显式移动它
你说:所以它们在 dom 内,但没有渲染,即使你的 CSS 告诉相反?
不,它们被渲染,就像任何普通的 DOM 元素一样。只是不再可见了。
您可以通过在 lightDOM 中包含 SCRIPT 标签来进行测试..它将渲染并执行!
在下面的代码片段中
您引用lightDOMthis.querySelector("span").innerHTML="weird";
但是引用shadowDOMthis.shadowRoot.querySelector("span").innerHTML="weird";
不起作用,因为 DIV(内部有 SPAN)被黑盒装在 <SLOT> 中
<foo-bar>
<h1>Test</h1>
</foo-bar>
Run Code Online (Sandbox Code Playgroud)
Chrome 和火狐浏览器:

DIV 不在 ShadowDOM/root 中,在 lightDOM 中保持不可见
,所有元素/样式将始终反映到 ShadowDOM/root
单击“reveal”将您带到 lightDOM
所以对于ShadowDOM 来说,开槽内容是元素和样式的黑匣子;从 lightDOM
反射
,这就是为什么::slotted只能设置盒子的样式,而不是里面的内容。
注意:在 F12 控制台中编辑该 DIV,您将看到更改立即反映到 ShadowDOM
通过更改,<slot name=...>您可以进行交互(想想路由、选项卡、答案),而以前需要更多的编码(还记得那些 jQuery 显示/隐藏的日子吗?)
<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>Run Code Online (Sandbox Code Playgroud)
更多与 SLOT 相关的答案可以通过 StackOverflow 搜索找到:自定义元素 SLOT