首先咱们先来看看它长什么样子。在HTML5中,咱们只用写以下简单的两行代码,就能够经过 <video> 标签来建立一个浏览器自带的视频播放器控件。javascript
<video controls=""> <source src="https://mdn.mozillademos.org/files/2587/AudioTest%20(1).ogg" type="audio/ogg"> </video>
而在各个浏览器中,它都有各不相同的外观展示,例如chrome中它长下面这样:java
但为何咱们在dom中没法看到他们内部的结构?噢,实际上浏览器经过某种技术把它们隐藏起来而已,但咱们能够经过 DevTools 设置中勾选Show user agent shadow DOM来看到这些结构。勾选后咱们发如今 <video> 标签下多了 #shadow-root(user-agent) 这个东西,它包含了 video 控件的内部dom结构,这就是所谓的shadow dom了。node
而且shadow dom为咱们提供了简单有效的样式隔离。若是你尝试经过 input[type="button"] { display:none; } 之类的样式来影响控件外观,你会发现是无效的。这样若是咱们经过 shadow dom 来隐藏控件的内部实现,就不用担忧对样式表进行修改时对控件形成影响了。web
下面咱们来看看如何经过shadow dom来封装控件。chrome
首先咱们先看看w3c对shadow dom的描述:浏览器
A shadow host is an element that hosts one or more node trees.app
A shadow tree is a node tree hosted by a shadow host.dom
A shadow root is the root node of a shadow tree.ide
这三句话告诉咱们:this
下面,咱们直接经过一个例子来演示如何使用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>
打开页面,咱们能够看到以下结构,这就是一个利用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>