使用shadow dom封装web组件
什么是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封装控件
首先我们先看看w3c对shadow 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>
- 第一步,我们需要一个shadow dom的容器 <div id="my-widget"></div>
- 随后通过 document.importNode() 获取到控件的模板并克隆
- 接着使用 createShadowRoot() 要创建一个shadow root作为shadow tree的根节点
- 最后将将模板内容 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>

使用shadow dom封装web组件的更多相关文章
- 【shadow dom入UI】web components思想如何应用于实际项目
回顾 经过昨天的优化处理([前端优化之拆分CSS]前端三剑客的分分合合),我们在UI一块做了几个关键动作: ① CSS入UI ② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀 ...
- atitit. web组件化原理与设计
atitit. web组件化原理与设计 1. Web Components提供了一种组件化的推荐方式,具体来说,就是:1 2. 组件化的本质目的并不一定是要为了可复用,而是提升可维护性. 不具有复用 ...
- atitit.atiHtmlUi web组件化方案与规范v1
atitit.atiHtmlUi web组件化方案与规范v1 1. 如何在现有html 标签基础上定义自己的组件1 2. 组件的构成与定义1 3. 组件的加载1 4. 组件css的加载2 5. 操作组 ...
- 究竟什么是Shadow DOM?
shadow dom 是什么? 顾名思义,shadow dom直译的话就是影子dom,但我更愿把它理解为DOM中的DOM.因为他能够为Web组件中的 DOM和 CSS提供了封装,实际上是在浏览器渲染文 ...
- 从原生web组件到框架组件源码(三)
快乐的时光都是这么短暂,转眼间,web原生组件的知识点已经学完了,这个虽然暂时不一定有用,但是随着时间的积累,一步一个脚印的积累,你会有相应的收获,希望能变得更强,比如两年前我也会想有现成的东西不用, ...
- JavaScript 是如何工作:Shadow DOM 的内部结构 + 如何编写独立的组件!
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 17 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...
- 【Web技术】401- 在 React 中使用 Shadow DOM
本文作者:houfeng 1. Shadow DOM 是什么 Shadow DOM 是什么?我们先来打开 Chrome 的 DevTool,并在 'Settings -> Preferences ...
- 【Web技术】400- 浅谈Shadow DOM
编者按:本文作者:刘观宇,360 奇舞团高级前端工程师.技术经理,W3C CSS 工作组成员. 为什么会有Shadow DOM 你在实际的开发中很可能遇到过这样的需求:实现一个可以拖拽的滑块,以实现范 ...
- JS21. 使用原生JS封装一个公共的Alert插件(HTML5: Shadow Dom)
效果预览 Shadow DOM Web components 的一个重要属性是封装--可以将标记结构.样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净.整 ...
随机推荐
- 关闭浏览器后Session失效原因分析
参考文章:http://www.tuicool.com/articles/VNbYjqm 首先需要理解一下几点: 1.Http是无状态的,即对于每一次请求都是一个全新的请求,服务器不保存上一次请求的信 ...
- 基本的mediaQuery写法,不复习又忘记了
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- 【BZOJ-3293&1465&1045】分金币&糖果传递×2 中位数 + 乱搞
3293: [Cqoi2011]分金币 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 854 Solved: 476[Submit][Status] ...
- 【codevs1200】 NOIP2012—同余方程
codevs.cn/problem/1200/ (题目链接) 题意 求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. Solution 这道题其实就是求${a~mod~b}$的逆元 ...
- 删除ecshop底部共执行个查询Gzip 已禁用,占用内存方法
删除ecshop底部共执行个查询Gzip 已禁用,占用内存方法 ECSHOP教程/ ecshop教程网(www.ecshop119.com) 2013-03-25 “共执行 41 个查询,用时 2 ...
- 【wget】一条命令轻松备份博客(包括图片)
h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...
- zabbix 汉化
zabbix2.x的版本自带汉化,3.x的版本也可以通过修改配置文件强制使用自带的汉化,但是不管哪种,翻译的精准度令人费解:偶然发现一个专门翻译zabbix的网站https://www.zabbix. ...
- python读写操作文件
with open(xxx,'r,coding='utf-8') as f: #打开文件赋值给F ,并且执行完了之后不需要 f.close(). 在Python 2.7 及以后,with又支持同时 ...
- JavaScript由单价、数量计算总价
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 开源项目剖析之apache-common-pool
前沿 该工程提供了对象池解决方案,该方案主要用于提高像文件句柄,数据库连接,socket通信这类大对象的调用效率.简单的说就是一种对象一次创建多次使用的技术. 整体结构 整个项目有三个包分别是org. ...