原文地址:Understanding Shadow DOM v1javascript
Shadow DOM 的誕生是爲了解決樣式衝突和選擇器失效的問題。它相似於一種新的 DOM 節點,或者說它能夠封裝了 HTML,能夠用於封裝一些小的組件,好比一個表單提交,咱們能夠建立一個 shadow 而後獨立的完整的呈現一個表單組件,而它不受外界影響。css
建立一個 shadow dom 使用 Element.attachShadow()
html
<div id="host"><p>Default text</p></div>
<script> const elem = document.querySelector('#host'); // attach a shadow root to #host const shadowRoot = elem.attachShadow({mode: 'open'}); // create a <p> element const p = document.createElement('p'); // add <p> to the shadow DOM shadowRoot.appendChild(p); // add text to <p> p.textContent = 'Hello!'; </script>
<!-- 其中不是每一種標籤均可以用於建立 shadow dom 的,上面是在 div 裏頭建立,像 img 就沒法,會報錯。 而後 attachShadow() 傳入一個對象參數,其餘 mode: 'open'/'closed' 兩種可選,這是 V1 添加的新特性,是必要屬性。 當 mode: 'closed' 時,是沒法經過 elem.shadowRoot 去獲取 shadow dom 元素的,由於這時候它是一個 null 像上述代碼的話, elem.shadowRoot 直接就指向咱們定義的變量 shadowRoot -->
複製代碼
樣式問題java
// shadowRoot 爲建立的 shadow dom 元素
shadowRoot.innerHTML = ` <p>Shadow DOM</p> <style>p {color: red;}</style>`
// 或者這樣
shadowRoot.innerHTML = ` <p>Shadow DOM</p> <link rel="stylesheet" href="style.css">`
// 而後咱們是能夠經過 給 shadow dom 元素設置樣式經過繼承去影響 shadow dom 裏面的元素樣式的
shadowRoot.innerHTML = ` <p>Shadow DOM</p> <style>#host {color: red;}</style>`
// 這樣經過樣式繼承,p 標籤的內容顏色也是紅色的
// 能夠經過 #root { all: initial; } 解決
複製代碼
自定義標籤也能夠用 shadow dom瀏覽器
<my-element></my-element>
<script> class MyElement extends HTMLElement { constructor() { // must be called before the this keyword super(); // attach a shadow root to <my-element> const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.innerHTML = ` <style>p {color: red}</style> <p>Hello</p>`; } } // register a custom element on the page customElements.define('my-element', MyElement); // 注意自定義元素的名字不能是單個單詞,my-element 能夠,myelement 不行! </script>
複製代碼
事件觸發問題app
<div id="host"></div>
<script> const elem = document.querySelector('#host'); const shadowRoot = elem.attachShadow({mode: 'open'}); shadowRoot.innerHTML = ` <ul> <li>One</li> <li>Two</li> <li>Three</li> <ul> `; document.addEventListener('click', (event) => { console.log(event.target); }, false); // 當你點擊 shadow dom 內的元素時,它會經過冒泡觸發 #host 的 div 元素,你沒法知道是容器裏面的具體那個元素點擊了 shadowRoot.querySelector('ul').addEventListener('click', (event) => { console.log(event.target); }, false); // 這樣就 ok </script>
複製代碼
shadow dom v0 是谷歌瀏覽器的規範,如今是 v1 版本,火狐和谷歌都有版本全面支持了,蘋果的嘛就只是部分支持,巨硬家的就還沒支持這個特性,就目前來講哈。dom
shadow dom 是 Web Components 的三個主要技術之一。ui