成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Shadow DOM 內(nèi)部構(gòu)造及如何構(gòu)建獨(dú)立組件

妤鋒シ / 1357人閱讀

摘要:此即如何實(shí)現(xiàn)局部樣式化的原理。這是一個絕佳的方式,開發(fā)者可以在組件內(nèi)部封裝響應(yīng)用戶交互或者狀態(tài)的行為,然后基于宿主元素來樣式化內(nèi)部節(jié)點(diǎn)。

原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。

這是 JavaScript 工作原理的第十七章。

概述

網(wǎng)頁組件指的是允許開發(fā)者使用一系列不同的技術(shù)來創(chuàng)建可復(fù)用的自定義元素,組件內(nèi)的功能不影響其它代碼,以便于開發(fā)者在網(wǎng)頁程序中使用。

有四種網(wǎng)頁組件標(biāo)準(zhǔn):

Shadow DOM

HTML 模板

自定義元素

HTML Imports

本章主要討論 Shadow DOM。

Shadow DOM 是一個被設(shè)計用來構(gòu)建基于組件(積木式)的網(wǎng)頁程序的工具。它為開發(fā)者可能經(jīng)常遇到過的問題提供了解決方案:

隔離的 DOM:組件的 DOM 是獨(dú)立的(比如 document.querySelector() 無法檢索到組件 shadow DOM 下的f元素節(jié)點(diǎn))。這樣就可以簡化網(wǎng)頁程序中的 CSS 選擇器,因為 DOM 組件是互不影響,這樣就允許開發(fā)者可以隨心所欲地使用更加通用的 id/class 命名而不用擔(dān)心命名沖突。

局部樣式: shadow DOM 內(nèi)定義的樣式不會污染 shadow DOM 之外的元素。Style 樣式規(guī)則不會泄漏且頁面樣式也不會污染 shadow DOM 內(nèi)的元素樣式。

組合:為開發(fā)者的組件設(shè)計一個聲明式,基于標(biāo)簽的接口。

Shadow DOM

本篇文章假設(shè)開發(fā)者已經(jīng)對 DOM 及其 API 熟拈于心。否則,可以閱讀一下這方面的詳細(xì)資料。

與一般的 DOM 元素相比,Shadow DOM 有兩處不同的地方:

與一般創(chuàng)建和使用 DOM 的方式相比,開發(fā)者如何創(chuàng)建及使用 Shadow DOM 及其與頁面上的其它元素的關(guān)系

其展現(xiàn)形式與頁面上的其它元素的關(guān)系

一般情況下,開發(fā)者創(chuàng)建 DOM 節(jié)點(diǎn),然后將其作為子元素掛載到其它元素下。對于 shadow DOM,開發(fā)者創(chuàng)建一個獨(dú)立 DOM 樹掛載到目標(biāo)元素下而該樹和其實(shí)際子元素是分離的。該獨(dú)立子樹稱為 shadow 樹。shadow 樹的掛載元素稱為 shadow 宿主。包括 Launch 模板

當(dāng)開發(fā)者不得不在網(wǎng)頁上復(fù)用相同的標(biāo)記結(jié)構(gòu)的時候,最好使用某種模板而不是重復(fù)書寫相同的頁面結(jié)構(gòu)。以前是可以實(shí)現(xiàn)的,但是現(xiàn)在可以使用

可以以如下方式使用剛才使用模板創(chuàng)建的自定義組件:

插槽

模板有一些不足的地方,主要的不足在于靜態(tài)內(nèi)容不允許開發(fā)者像一般的標(biāo)準(zhǔn) HTML 模板那樣渲染自定義的變量或者數(shù)據(jù)。

這時候 就派上用場了。

可以把插槽看成是允許開發(fā)者在模板中放置自定義 HTML 的占位符的功能。這樣開發(fā)者就可以創(chuàng)建能用的 HTML 模板并且通過引入插槽來自定義渲染內(nèi)容。

讓我們看一下以上模板添加一個插槽的代碼如下:

如果在標(biāo)記中引用該元素的時候沒有定義插槽內(nèi)容,或者瀏覽器不支持插槽,則 只會包含默認(rèn)的 "Default text" 內(nèi)容。

若想要定義插槽內(nèi)容,開發(fā)者得在 中定義元素 HTML 結(jié)構(gòu)的 slot 屬性值和對應(yīng)填充的插槽名稱保持一致即可。

如前所述,開發(fā)者可以隨便寫插槽內(nèi)容:


 Let"s have some different text!

所有可以被插入插槽的元素被稱為可插入元素;已插入插槽元素稱為插槽元素。

注意以上示例中插入的 元素即是插槽元素。它擁有一個 slot 屬性,屬性值和模板中插槽定義的 name 屬性值相等。

瀏覽器渲染之后,以上代碼會創(chuàng)建如下扁平 DOM 樹:


  #shadow-root
  

Default text

Let"s have some different text!

這里原文有誤,有改動。

注意 #shadow-root 元素只是表示存在 Shadow DOM 而已。

樣式化

可以在主頁面樣式化含有 shadow DOM 的組件,可以定義組件樣式或者提供 CSS 自定義屬性的形式讓用戶覆蓋掉默認(rèn)樣式值。

組件定義的樣式

局部樣式 是 Shadow DOM 極好的功能之一:

主頁面上的 CSS 選擇器不會影響到組件內(nèi)部元素的樣式。

組件內(nèi)部定義的樣式不會影響頁面上的其它元素樣式。它們只作用于宿主元素。

Shadow DOM 中的 CSS 選擇器只影響組件內(nèi)部的元素。實(shí)際上,這意味著開發(fā)者可以重復(fù)使用通用的 id/class 名稱而不用擔(dān)心和主頁面上的其它樣式發(fā)生沖突。簡單的 CSS 選擇器可以提高頁面性能。

讓我們看一下如下 #shadow-root 中定義的一些樣式:

#shadow-root


以上示例中的樣式只會作用于 #shadow-root 內(nèi)部。

開發(fā)者也可以在 #shadow-root 里面使用 元素來引入樣式表,也只作用于 #shadow-root 內(nèi)部。

:host 偽類

:host 偽類允許開發(fā)者選擇和樣式化包含 shadow 樹的宿主元素:

只有一個地方需要注意即若主頁面上定義的宿主元素樣式優(yōu)先級比元素里面定義的 :host 樣式規(guī)則要高。這樣就允許開發(fā)者從外部覆蓋掉組件內(nèi)部定義的頂級樣式。

即當(dāng)在主頁面上定義了如下的樣式:

my-paragraph {
  marbin-bottom: 40px;
}

同理,:host 只在shadow 根的上下文中起作用,因此開發(fā)者不能夠在 Shadow DOM 外面使用。

:host() 這樣的功能樣式允許開發(fā)者只樣式化匹配 的宿主元素。這是一個絕佳的方式,開發(fā)者可以在組件內(nèi)部封裝響應(yīng)用戶交互或者狀態(tài)的行為,然后基于宿主元素來樣式化內(nèi)部節(jié)點(diǎn)。

使用 :host-context() 偽類來定制化元素樣式

:host-context() 偽類找出宿主元素或者宿主元素任意的祖先元素匹配 。

常用于定制化。例如,開發(fā)者通過為 或者 添加類來進(jìn)行定制化:


  

或者

當(dāng)宿主元素的祖先元素包含有 .lightheme 類 :host-context(.lightheme) 將會樣式化

:host-context(.lightheme) {
  color: black;
  background: white;
}

可以使用 :host-context() 來進(jìn)行定制化主題樣式,但是更好的方法即通過 CSS 自定義屬性來創(chuàng)建樣式鉤子。

從外部樣式化組件宿主元素

開發(fā)者可以從外部通過把標(biāo)簽名作為選擇器來樣式化組件宿主元素,如下:

custom-container {
  color: red;
}

外部樣式比 Shadow DOM 中定義的樣式擁有更高的優(yōu)先級。

例如,假設(shè)用戶書寫如下選擇器:

custom-container {
  width: 500px;
}

將會覆蓋如下組件樣式規(guī)則 :

:host {
  width: 300px;
}

組件自身樣式化只能做到這么多。但如果想要樣式化組件內(nèi)部屬性呢?這就需要 CSS 自定義屬性。

使用 CSS 自定義屬性來創(chuàng)建樣式鉤子

若組件作者使用 CSS 自定義屬性提供樣式鉤子,用戶可以用來更改內(nèi)部樣式。

這和 思路類似只是應(yīng)用到了樣式。

讓我們看如下示例:




Shadow DOM 內(nèi)部:

:host([background]) {
  background: var(--custom-container-bg, #CECECE);
  border-radius: 10px;
  padding: 10px;
}

該示例中,因為用戶提供了該背景顏色值,所以組件將會把黑色作為背景顏色值。否則,默認(rèn)為 #CECECE

作為組件作者,需要讓開發(fā)者知道可以使用的 CSS 自定義屬性??梢园炎远x屬性看作組件的公共接口。

插槽 JavaScript 接口

Shadow DOM API 可能用來操作插槽。

slotchange 事件

當(dāng)一個插槽的分發(fā)元素節(jié)點(diǎn)發(fā)生變化的時候觸發(fā) slotchange 事件。例如,當(dāng)用戶從 light DOM 中添加/刪除子節(jié)點(diǎn)。

var slot = this.shadowRoot.querySelector("#some_slot");
slot.addEventListener("slotchange", function(e) {
  console.log("Light DOM change");
});

可以在元素的構(gòu)造函數(shù)中創(chuàng)建 MutationObserver 來監(jiān)聽 light DOM 的其它類型的修改事件。前面文章中有介紹過 MutationObserver 的內(nèi)部構(gòu)造及使用指南。

assignedNodes() 方法

了解哪些元素是和插槽有關(guān)是很有用處的。調(diào)用 slot.assignedNodes() 可以找出哪些元素是由插槽渲染的。flatten: true} 選項會返回插槽的默認(rèn)內(nèi)容(若沒有分發(fā)任何節(jié)點(diǎn))。

看一下如下示例:

Default content

假設(shè)以上內(nèi)容包含在一個叫做 的組件內(nèi)部。

讓我們查看一下該組件的不同用法,然后調(diào)用 assignedNodes() 輸出不同的結(jié)果:

第一例中,我們將往插槽中添加內(nèi)容:


   container text 

調(diào)用 assignedNodes() 將會返回 [ container text ]。注意結(jié)果為一個節(jié)點(diǎn)數(shù)組。

第二例中,將不添加內(nèi)容:

調(diào)用 assignedNodes() 將會返回空數(shù)組 []。

但是,假設(shè)添加 {flatten: true} 參數(shù)將會返回默認(rèn)內(nèi)容:[

Default content

]

同理,為了查找插槽中的元素,開發(fā)者可以調(diào)用 assignedNodes() 來找出元素被掛載到哪個組件插槽中。

事件模型

Shadow DOM 中的事件冒泡的經(jīng)過是值得注意的。

事件目標(biāo)被調(diào)整為維護(hù) Shadow DOM 的封閉性。當(dāng)事件被重新定位,看起來是由組件自身產(chǎn)生而不是組件的 Shadow DOM 內(nèi)部元素。

這里有傳播出 Shadow DOM 的事件列表(還有一些只能在 Shadow DOM 內(nèi)傳播):

Focus 事件:blur, focus, focusin, focusout

鼠標(biāo)事件:click, dblclick, mousedown, mouseenter, mousemove 等.

滾輪事件: wheel

輸入事件: beforeinput, input

鍵盤事件: keydown, keyup

組合事件: compositionstart, compositionupdate, compositionend

拖拽事件: dragstart, drag, dragend, drop 等.

自定義事件

默認(rèn)情況下,自定義事件不會傳播出 Shadow DOM。開發(fā)者若想要分派自定義事件且想要傳播出 Shadow DOM,需要添加 bubbles: truecomposed: true 選項參數(shù)。

讓我們瞧瞧類似這樣的事件分派:

var container = this.shadowRoot.querySelector("#container");
container.dispatchEvent(new Event("containerchanged", {bubbles: true, composed: true}));
瀏覽器兼容情況

可以通過檢查 attachShadow 來檢查是否支持 Shadow DOM 功能:

const supportsShadowDOMV1 = !!HTMLElement.prototype.attachShadow;

參考資料:

https://developer.mozilla.org...

https://developers.google.com...

https://developer.mozilla.org...

https://www.html5rocks.com/en...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/102259.html

相關(guān)文章

  • JavaScript 是如何工作: Shadow DOM內(nèi)部結(jié)構(gòu)+如何編寫獨(dú)立組件

    摘要:向影子樹添加的任何內(nèi)容都將成為宿主元素的本地元素,包括,這就是影子實(shí)現(xiàn)樣式作用域的方式。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 17 篇。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 如果你錯過了前面的章節(jié),可以在這里找到它們: JavaScript 是如何工作的:引擎,運(yùn)行時和調(diào)用堆棧的概述! JavaScript 是如何工作...

    godlong_X 評論0 收藏0
  • 純原生組件化-模塊化的探索

    摘要:純原生的組件化模塊化的一次小小的嘗試,用到了如下幾個新特性對標(biāo)簽結(jié)構(gòu)的一個封裝,真正意義上的組件,能保證中的元素不會被外界影響,內(nèi)部也不會影響到外部的行為,變成了一個獨(dú)立的模塊。 純原生的組件化、模塊化的一次小小的嘗試,用到了如下幾個新特性:shadown-DOM 對HTML標(biāo)簽結(jié)構(gòu)的一個封裝,真正意義上的組件,能保證 shadow-DOM 中的DOM元素不會被外界影響,內(nèi)部也不會影響...

    張金寶 評論0 收藏0
  • 自定義元素探秘構(gòu)建可復(fù)用組件最佳實(shí)踐

    摘要:若自定義元素標(biāo)簽名稱不可用則摒棄??傊远x元素讓開發(fā)者的代碼更易理解和維護(hù),并分割為小型,可復(fù)用及可封裝的模塊。被稱為自定義元素接口,雖然現(xiàn)在仍然可用,但是已經(jīng)被棄用并被認(rèn)為是糟糕的實(shí)現(xiàn)。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。 這是 JavaScript 工作原理第十九章。 概述 在 前述文章中,我們介紹了 Shadow ...

    CoorChice 評論0 收藏0
  • # Web Components 全攬

    摘要:定制元素可以在原生元素外創(chuàng)建定制元素。此定制元素內(nèi)部有一個加號按鈕,一個減號按鈕,一個顯示當(dāng)前值。此主題會在下一部分內(nèi)介紹。定制元素的屬性元素的屬性被稱為,對象內(nèi)的屬性被稱為。做響應(yīng)的同步處理。 Web Components 全攬 Web Components技術(shù)可以把一組相關(guān)的HTML、JS代碼和CSS風(fēng)格打包成為一個自包含的組件,只要使用大家熟悉的標(biāo)簽即可引入此組件。Web Com...

    legendmohe 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<