使用shadow dom封裝web組件

/*http://www.cnblogs.com/WhiteCusp/p/4342502.htmlutm_source=tuicool&utm_medium=referral*/

什麼是shadow dom?

首先我們先來看看它長什麼樣子。在HTML5中,我們只用寫如下簡單的兩行代碼,就可以通過 <video> 標籤來創建一個瀏覽器自帶的視頻播放器控件。

<video controls="">
    <source src="https://mdn.mozillademos.org/files/2587/AudioTest%20(1).ogg" type="audio/ogg">
</video>

而在各個瀏覽器中,它都有各不相同的外觀展現,例如chrome中它長下面這樣:

但爲什麼我們在dom中無法看到他們內部的結構?噢,實際上瀏覽器通過某種技術把它們隱藏起來而已,但我們可以通過 DevTools 設置中勾選Show user agent shadow DOM來看到這些結構。勾選後我們發現在 <video> 標籤下多了 #shadow-root(user-agent) 這個東西,它包含了 video 控件的內部dom結構,這就是所謂的shadow dom了。

並且shadow dom爲我們提供了簡單有效的樣式隔離。如果你嘗試通過 input[type="button"] { display:none; } 之類的樣式來影響控件外觀,你會發現是無效的。這樣如果我們通過 shadow dom 來隱藏控件的內部實現,就不用擔心對樣式表進行修改時對控件造成影響了。

下面我們來看看如何通過shadow dom來封裝控件。

使用Shadow Dom封裝控件

首先我們先看看w3cshadow dom的描述:

A shadow host is an element that hosts one or more node trees.

A shadow tree is a node tree hosted by a shadow host.

A shadow root is the root node of a shadow tree.

這三句話告訴我們:

  • - shadow dom 由一顆或多顆 shadow tree 組成,並且需要一個普通的dom元素作爲它的容器
  • - shadow tree 是一顆節點樹
  • - shadow root 是shadow tree的根節點

下面,我們直接通過一個例子來演示如何使用shadow dom來封裝web組件:

DOM:

複製代碼
 // 模板
<template id="wgTemplate">
  <style>
      color: #fff;
      background: #006dcc;
  </style>
  <button type="button" class="btn">button widget</button>
</template>

// shadow dom 容器
<div id="my-widget"></div>
複製代碼

JS:

複製代碼
// 創建shadow dom
<script type='text/javascript'>
  var host = document.querySelector("#my-widget")
  var tp = document.querySelector("#wgTemplate")
  var clone = document.importNode(tp.content, true)
  host.createShadowRoot().appendChild(clone)
</script>
複製代碼
  1. 第一步,我們需要一個shadow dom的容器 <div id="my-widget"></div> 
  2. 隨後通過 document.importNode() 獲取到控件的模板並克隆
  3. 接着使用 createShadowRoot() 要創建一個shadow root作爲shadow tree的根節點
  4. 最後將將模板內容 clone 作爲shadow tree插入到shadow root

打開頁面,我們可以看到如下結構,這就是一個利用shadow隱藏控件內部實現最簡單的例子了。

接着我們還可以結合上一篇文章《web component之custom element》的創建自定義元素的方法來封裝自定義控件

dom:

複製代碼
// 模板
<template id="wgTemplate">
  <style>
    .btn {
      color: #fff;
      background: #006dcc;
    }
  </style>
  <button type="button" class="btn">custom button widget</button>
</template>
複製代碼

js:

複製代碼
 // 創建自定義控件
<script type='text/javascript'>
  var proto = Object.create(HTMLElement.prototype, {
    createdCallback: {
      value: function() {
        var tp = document.querySelector('#wgTemplate')
        var clone = document.importNode(tp.content, true)
        this.createShadowRoot().appendChild(clone)
      }
    }
  })

  var MyButtom = document.registerElement('my-buttom', {prototype: proto})
  
  document.body.appendChild(new MyButtom())
</script>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章