Web Components 系列主要由自定義元素(Custom Elements)、HTML 引入(HTML Imports)和影子 DOM(shadow DOM) 組成,而 Shadow DOM 無疑是當中的重中之重。本文對下面翻譯的幾篇文章進行綜述,總結了 Shadow DOM 術語梳理和結構關係。html
影子 DOM(shadow DOM):是一種依附於文檔原有節點的子 DOM,具備封裝性html5
光明 DOM(light DOM):就是原生的 DOM,爲了與影子 DOM 區別採用的名詞node
影子樹(shadow trees):特指存在於 shadow DOM 中的節點結構web
影子宿主(shadow host):特指 shadow DOM 所依附的影子宿主,是存在於原生 DOM 中的節點dom
影子根(shadow root):指 shadow DOM 的根節點ide
插入點(insertion point):指 shadow DOM 中的 <content>
標籤spa
貪心插入點(greedy insertion point):指使用通配符選擇器進行匹配的插入點.net
影子邊界(shadow boundary):指對影子 DOM 與光明 DOM 進行的樣式隔離,二者中的樣式不會相互影響。翻譯
分佈節點(distributed nodes):指本來存在於光明 DOM 結構中,被 <content>
標籤添加到影子 DOM 中的節點。code
影子 DOM 必須依附於一個文檔中的原有 DOM 節點,也就是影子宿主,而影子 DOM 中的節點也能夠成爲另外一個影子樹的宿主。在 Web Components 的實際使用場景中,宿主通常是自定義元素,而在影子 DOM 中封裝了其實現細節。
影子 DOM 樹被影子邊界所包裹,邊界給其帶來了封裝性,這一封裝性包括:
DOM 的封裝性:在不一樣的 DOM 樹中沒法選擇另外 DOM 中的元素,只有獲取對應的 DOM 樹才能對其中的元素進行操做;
樣式的封裝性:在不一樣的 DOM 樹中樣式沒法相互影響,只有經過一系列手段突破邊界才能對對方的樣式進行操做。其中經過影子 DOM 來對宿主 DOM 進行操做的方式多種多樣:
須要注意的是,單獨使用 ::content
選擇器沒有意義,這表示對插入點進行的樣式修飾,而插入點是不展示的;因此該選擇器的出現必然跟隨者子選擇器,以便對分佈節點進行樣式影響。
而光明 DOM 對於影子 DOM 的影響卻要弱不少,且原則上來說,影子 DOM 存在的意義就是爲了對子 DOM 進行封裝,而實現自定義元素對外部隱藏細節的效果。若是用戶要求進行影響的話,這裏也存在兩個大殺器:一層穿透 ::shadow
僞類選擇器與多重穿透 /deep/
組合符。
對宿主自己進行樣式影響:經過 :host
選擇器
對宿主的祖先節點進行樣式影響:經過 :host-context
選擇器
對分佈節點進行影響:經過 ::content
選擇器
JS 的重定向與阻塞:影子邊界對於 JS 的阻塞是最弱的,它僅僅阻塞了一部分事件, 同時將影子 DOM 中的事件重定向到宿主上。關於事件重定向,Eric Bidelman 的 Shadow DOM 301 講的更爲細緻一點,事實上重定向僅僅是表示影子 DOM 中的事件冒泡沒法經過影子邊界,而在邊界內部的事件監聽仍是有效果的。咱們也能夠經過 event.path
來查看調整後的事件路徑,並找到事件在影子 DOM 中的真正源頭。
光明 DOM 與影子 DOM 的結構關係以下圖所示:
圖中藍線表示樣式影響方式,紅線表示 DOM 影響方式,黃線表示 JS 影響方式。
在影子 DOM 中,<link>
標籤時被忽略的,所以不能用外鏈的方式引入 CSS 文件。在 Polymer 中咱們能夠這樣作,是由於 Polymer 將 <link>
節點轉化爲了 <style>
節點所致。在原生的實現上要注意這一點。