天天看點

Shadow DOM的了解

Shadow DOM的了解

Shadow DOM

HTML

的一個規範,其允許在文檔

document

渲染時插入一顆

DOM

元素子樹,但是這棵子樹不在主

DOM

樹中,

Shadow DOM

如果按照英文翻譯的話可以翻譯為影子

DOM

,是一種不屬于主

DOM

樹的獨立的結構。

描述

Web components

的一個重要屬性是封裝——可以将标記結構、樣式和行為隐藏起來,并與頁面上的其他代碼相隔離,保證不同的部分不會混在一起,可使代碼更加幹淨、整潔,在這裡

Shadow DOM

接口是關鍵所在,它可以将一個隐藏的、獨立的

DOM

附加到一個元素上,

Shadow DOM

标準允許你為你自己的元素

custom element

維護一組

Shadow DOM

Shadow DOM

允許将隐藏的

DOM

樹附加到正常的

DOM

樹中,它以

shadow root

節點為起始根節點,在這個根節點的下方,可以是任意元素,和普通的

DOM

元素一樣,另外還有一些

Shadow DOM

特有的術語。

  • Shadow host

    : 一個正常

    DOM

    節點,

    Shadow DOM

    會被附加到這個節點上。
  • Shadow tree

    :

    Shadow DOM

    内部的

    DOM

    樹。
  • Shadow boundary

    Shadow DOM

    結束的地方,也是正常

    DOM

    開始的地方。
  • Shadow root

    Shadow tree

    的根節點。

我們可以使用同樣的方式來操作

Shadow DOM

,就和操作正常

DOM

一樣——例如添加子節點、設定屬性,以及為節點添加自己的樣式(例如通過

element.style

屬性),或者為整個

Shadow DOM

添加樣式(例如在

<style>

元素内添加樣式),不同的是

Shadow DOM

内部的元素始終不會影響到它外部的元素(除了

:focus-within

),這就為封裝提供了便利。

此外不管從哪個方面來看

Shadow DOM

都不是一個新事物,在過去的很長一段時間裡,浏覽器用它來封裝一些元素的内部結構,以一個有着預設播放控制按鈕的

<video>

元素為例,我們所能看到的隻是一個

<video>

标簽,實際上,在它的

Shadow DOM

中,包含來一系列的按鈕和其他控制器。再舉一個例子我們都知道像

React

Vue

這樣的都有元件的概念,我們常用的

<input>

<audio>

<video>

等這些元素,其實它也是以元件的形式存在的,即

HTML Web Component

這些都有自己的

Shadow DOM

,這些元件内部是由自身的一些

HTML

标簽組成的。

現代浏覽器

Firefox

Chrome

Opera

Safari

等預設支援

Shadow DOM

,基于

Chromium

的新

Edge

也支援

Shadow DOM

,而舊

Edge

未能撐到支援此特性,至于

IE

浏覽器嘛

...

,相容性方面可以查閱此處

https://caniuse.com/?search=Shadow%20DOM

示例

<!DOCTYPE html>
<html>

<head>
    <title>Shadow DOM</title>
    <style>
        .text{
            color: blue; /* 設定字型顔色 */ /* 可以看出在外部定義的樣式無法影響到影子内部元素樣式 */
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="shadow-cls"></div>
    </div>
</body>

<script type="text/javascript">
    (function(doc, win){
        var shadowHost = doc.querySelector(".shadow-cls"); // 擷取影子宿主shadow host
        var shadowRoot = shadowHost.attachShadow({mode: "open"}); // 建立(附加)影子shadow root // open 表示可以通過頁面内的 JavaScript 方法來擷取 Shadow DOM
        var style = doc.createElement("style"); // 建立style元素
        style.textContent = `
            .text{
                font-style: italic;
            }
        `; // 影子内部樣式
        const template = `
          <div>
              <div class="text">Text</div>
          </div>
        `; // 模闆 // 另外可以嘗試 <template> 以及 <script text/template>
        const container = doc.createElement("div"); // 建立容器
        container.innerHTML = template; // 加入容器
        shadowRoot.append(style, container); // 加入影子
    })(document, window);
</script>
</html>
           

每日一題

https://github.com/WindrunnerMax/EveryDay
           

參考

https://segmentfault.com/a/1190000017970486
https://www.cnblogs.com/tugenhua0707/p/10545179.html
https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM