使用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 的一个重要属性是封装--可以将标记结构.样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净.整 ...
随机推荐
- [转]Java中的对象和对象引用实例浅析
在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起了解一下对象和对象引用之间的区别 ...
- if...else语句的应用题
应用题 namespace ConsoleApplication1 { /* 题目要求:提示用户输入年龄,如果大于等于18,那么用户可以查看.如果小于10岁,则告知用户”少儿不宜“. 如果大于等于10 ...
- hdu2444 判断二分图+最大匹配
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define ...
- Java基础-静态代理与动态代理比较
JAVA的静态代理与动态代理比较 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类: 在程序运行时,运用反射机制动态创建 ...
- StyleCop的常见错误
所有规则的翻译(基于版本4.7.44.0): 文档规则 1.SA1600:ElementsMustBeDocumented元素必须添加注释 2.SA1601: PartialElementsMustB ...
- Session解析
1.除非关闭所有页面 或者超时session才销毁 2.在几个页面之间切换的时候 session保存用户状态. 3.遍历数组时候for循环中从0开始小于长度,不等于长度,用Matlab用习惯了,竟然从 ...
- Spring学习8-Spring事务管理(编程式事务管理)
一.Spring事务的相关知识 1.事务是指一系列独立的操作,但在概念上具有原子性. 比如转账:A账号-100, B账号+100,完成.这两个操作独立是没问题的. 但在逻辑上,要么全部完成,要么一 ...
- UVa OJ 180 - Eeny Meeny
Time limit: 3.000 seconds限时3.000秒 Problem问题 In darkest <name of continent/island deleted to preve ...
- Logistic Regression and Gradient Descent
Logistic Regression and Gradient Descent Logistic regression is an excellent tool to know for classi ...
- dedecms最新版本修改任意管理员漏洞
此漏洞无视gpc转义,过80sec注入防御. 补充下,不用担心后台找不到.这只是一个demo,都能修改任意数据库了,还怕拿不到SHELL? 起因是全局变量$GLOBALS可以被任意修改,随便看了下,漏 ...