簡體   English   中英

為什么我的 shadow dom 會破壞我的自定義元素?

[英]Why does my shadow dom break my custom element?

這是自定義元素的 JSFiddle 演示: https ://jsfiddle.net/c4bLo097/5/

這是小提琴中的代碼:

JavaScript:

window.customElements.define('test-element', class TestElement extends HTMLElement {
    constructor() {
    super()

    let contents = `
      <style>
        :host {
          display: block;
        }
        :host([hidden]) {
          display: none;
        }
      </style>`

    // convert string to nodes
    let template = document.createElement('template')
    template.innerHTML = contents

    // create shadow
    this.attachShadow({mode: 'open'})

    // insert nodes
    this.shadowRoot.appendChild(template.content.cloneNode(true))
  }
})

HTML:

<test-element>
    This element should have a natural height.

    <div style="height: 300px;"></div>

    I should be able to see this text on a green background.
</test-element>

CSS:

test-element {
  width: 200px;
  background: green;
}

如果您使用開發人員工具檢查<custom-element> ,您應該會看到陰影在那里。 但是我的元素不會正確呈現其高度。

這是我試圖實現的一個示例 JSFiddle: https ://jsfiddle.net/9483s1qb/2/

當您添加 shadowDOM 時,元素的內容將變為“lightDOM”。

不再顯示在主 DOM 中也不是 shadowDOM 的一部分。

正如Supersharp 在 2017 年解釋的那樣

Light DOM 只是 HTML 元素內的普通舊 DOM 樹。

該術語僅用於 Web 組件(帶有 Shadow DOM 的自定義元素)的上下文中
我想與Shadow相比,普通 DOM 被重新定義為Light

WHATWG 規范將其稱為 shadowroot 主機的節點樹光樹

Shadow DOM 是添加的 DOM,用於恢復、屏蔽或替換普通 DOM,
谷歌文章所述

您必須自己將 lightDOM 內容傳輸到 shadowDOM:

 customElements.define('my-element', class extends HTMLElement { constructor() { //create shadowDOM (thus creating lightDOM) and append Template super() /* return this */ .attachShadow({mode: 'open'}) /* SETs and RETURNs this.shadowRoot */ .append(document.getElementById(this.nodeName).content.cloneNode(true)) } connectedCallback(){ //append content from lightDOM this.shadowRoot.append(...this.querySelectorAll('DIV')); } })
 my-element{ border: 1px dashed blue; }
 <template id="MY-ELEMENT"> <style> :host { display: block; font-size:20px; } h4{ background:yellow; margin: .5em 0; } div{ background:lightcoral; } </style> <h4><slot name="title"></slot></h4> </template> <my-element> <!-- begin lightDOM because my-element has shadowDOM --> <span slot="title">whole SPAN is slotted</span> <div>I am appended</div> <div>appended too</div> <p>I remain (invisible) in lightDOM</p> <!-- end lightDOM --> </my-element> <my-element> <!-- begin lightDOM because my-element has shadowDOM --> <span slot="title">slotted too</span> <div>appended again</div> I remain (invisible) in lightDOM <!-- end lightDOM --> </my-element>

片段注釋:

  • 模板被克隆

  • connectedCallbackappend移動內容,
    如果您想將原始文件保留在 lightDOM 中(例如,將其用作數據存儲)
    你必須像使用template一樣克隆它。

  • slot="title"將整個span (包括跨度!)反映到它在 shadowDOM 中的插槽中
    請參閱:::slotted CSS 選擇器用於 shadowDOM 插槽中的嵌套子項

  • 自己試試:
    在 JSFiddle 游樂場: https ://jsfiddle.net/CustomElementsExamples/bzvLcxfe/

  • 未命名的: <slot></slot>什么?

  • 如果將<span>更改為<div>會發生什么

意識到!! 瀏覽器行為不同!

當(主)DOM 尚未實例化時,您可能需要connectedCallback使用setTimeout

    connectedCallback() {
      let savedHTML = this.outerHTML;
      //append content from lightDOM
      const append = (selector) =>
        this.shadowRoot.append(...this.querySelectorAll(selector), savedHTML);

      if (this.outerHTML.includes("timeout"))
        setTimeout(() => append('DIV'))
      else
        append('DIV');
    }

JSFiddle 游樂場: https ://jsfiddle.net/CustomElementsExamples/bzvLcxfe/

  • 在第一個黃色元素 DIV 中附加沒有setTimeout

  • 第二黃色元素的DIV附加一個setTimeout

  • 兩個元素中都附加了outerHTMLconnectedCallback已知)。

結果在 ( Chromium ) Chrome\\Edge\\Opera:

  • lightDOM不可用,
    setTimeout需要延遲代碼直到事件循環完成,並且 lightDOM 可用。

結果在(壁虎)火狐:

  • lightDOM可用沒有setTimeout需要

Safari 中的結果:

  • 我不知道(還)請告訴我

筆記:

  • customElements.defineDOM 准備好之前運行時(在 Chromium 瀏覽器中)會發生這種情況。 如果在創建 DOM 元素更改JSFiddle並執行<script>塊,則一切正常。
    (但大多數情況下,您會盡快加載庫以防止FOUC

  • connectedCallback中的requestAnimationFrame connectedCallback setTimeout具有相同的行為。 更多詳情: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

  • 當您加載內容異步的DOM也可能准備
    <script src=elements.js async ></script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM