gpt4 book ai didi

javascript - 如果没有 `` 而是影子根,子节点会发生什么

转载 作者:行者123 更新时间:2023-12-01 15:42:08 25 4
gpt4 key购买 nike

考虑这段代码:

//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属性(property)遗存 "" .所以它们在dom内,但没有渲染,即使你的css告诉相反的?这里到底发生了什么?

最佳答案

完整的详细解释在:::slotted CSS selector for nested children in shadowDOM slot

<foo-bar>
<h1>Test</h1>
</foo-bar>
H1 是 lightDOM ,
“添加” shadowDOM/root 内容是 反射(reflect) shadowDOM ,没动!!!
H1 始终保留在 lightDOM 中:
  • 隐形 (在页面中)在 lightDOM 对于元素 shadowDOM/根目录,
  • 可见 (在页面中)自定义元素 没有 shadowDOM/根
  • 除非你用 appendChild 明确地移动它(或任何 DOM 移动操作)

  • 你说:所以它们在 dom 内,但没有渲染,即使你的 CSS 告诉相反的?
    不,他们 渲染,就像任何普通的 DOM 元素一样。只是不再可见。
    您可以通过在 lightDOM 中包含一个 SCRIPT 标记来进行测试。它将 渲染 并执行!

    在下面的代码片段中
    您引用 lightDOM this.querySelector("span").innerHTML="weird";但引用 shadowDOM 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 和火狐:

    DIV 不在 shadowDOM/root 中,仍然是 隐形在 lightDOM 中
    所有元素/样式将始终 反射(reflect) 到 shadowDOM/root
    单击“显示”将带您进入 lightDOM

    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,您将立即看到更改 反射(reflect) 到 shadowDOM

    SLOT 和 lightDOM 是实时连接
    通过更改 <slot name=...>您可以进行以前需要更多编码的交互(想想路线、选项卡、答案)(还记得那些 jQuery 显示/隐藏的日子吗?)

    <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 相关的答案可以通过 StackOverflow 搜索找到: Custom Elements SLOTs

    关于javascript - 如果没有 `<slot/>` 而是影子根,子节点会发生什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61852233/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com