什么是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>

使用shadow dom封装web组件的更多相关文章

  1. 【shadow dom入UI】web components思想如何应用于实际项目

    回顾 经过昨天的优化处理([前端优化之拆分CSS]前端三剑客的分分合合),我们在UI一块做了几个关键动作: ① CSS入UI ② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀 ...

  2. atitit.  web组件化原理与设计

    atitit.  web组件化原理与设计 1. Web Components提供了一种组件化的推荐方式,具体来说,就是:1 2. 组件化的本质目的并不一定是要为了可复用,而是提升可维护性. 不具有复用 ...

  3. atitit.atiHtmlUi web组件化方案与规范v1

    atitit.atiHtmlUi web组件化方案与规范v1 1. 如何在现有html 标签基础上定义自己的组件1 2. 组件的构成与定义1 3. 组件的加载1 4. 组件css的加载2 5. 操作组 ...

  4. 究竟什么是Shadow DOM?

    shadow dom 是什么? 顾名思义,shadow dom直译的话就是影子dom,但我更愿把它理解为DOM中的DOM.因为他能够为Web组件中的 DOM和 CSS提供了封装,实际上是在浏览器渲染文 ...

  5. 从原生web组件到框架组件源码(三)

    快乐的时光都是这么短暂,转眼间,web原生组件的知识点已经学完了,这个虽然暂时不一定有用,但是随着时间的积累,一步一个脚印的积累,你会有相应的收获,希望能变得更强,比如两年前我也会想有现成的东西不用, ...

  6. JavaScript 是如何工作:Shadow DOM 的内部结构 + 如何编写独立的组件!

    这是专门探索 JavaScript 及其所构建的组件的系列文章的第 17 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...

  7. 【Web技术】401- 在 React 中使用 Shadow DOM

    本文作者:houfeng 1. Shadow DOM 是什么 Shadow DOM 是什么?我们先来打开 Chrome 的 DevTool,并在 'Settings -> Preferences ...

  8. 【Web技术】400- 浅谈Shadow DOM

    编者按:本文作者:刘观宇,360 奇舞团高级前端工程师.技术经理,W3C CSS 工作组成员. 为什么会有Shadow DOM 你在实际的开发中很可能遇到过这样的需求:实现一个可以拖拽的滑块,以实现范 ...

  9. JS21. 使用原生JS封装一个公共的Alert插件(HTML5: Shadow Dom)

    效果预览 Shadow DOM Web components  的一个重要属性是封装--可以将标记结构.样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净.整 ...

随机推荐

  1. VS插件之小番茄

    文件源以及安装说明! http://www.youranshare.com/app/98.html

  2. Java基础-JVM

    jvm=> java虚拟机 一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止. ...

  3. 【poj2724】 Purifying Machine

    http://poj.org/problem?id=2724 (题目链接) 题意 Mike有一个机器可以帮助他清理奶酪,每个奶酪由一个n位二进制数表示,机器上一共有n个按钮,每个按钮有1,0,*,其中 ...

  4. BZOJ1086 [SCOI2005]王室联邦

    Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成 员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个 ...

  5. 使用U盘安装mint

    系统坏了,重新装的时候,硬盘甚至都没法格式化...所以,狠狠心买了块固态硬盘,123G,威刚. 想自己装Linux系统,这样用起来更方便一点,不用装虚拟机,然后再跑linux什么的.最后选了mint. ...

  6. debian , ubuntu 截取下拉菜单

    普通情况下print键很好用的,但是,截下拉菜单的时候,就怎么按都没反应了...然后换了shutter也不行,只能在静态界面截图.所以...然后就有了下面方法. 如果不是gnome怎么办?这个担心显然 ...

  7. 迷宫问题(bfs)

    import java.util.LinkedList; import java.util.Queue; import java.util.Stack; public class BFS { priv ...

  8. a[1000][1000]程序崩溃

    1000 * 1000是大于65536的.如果不是需求需要,没必要开辟如此之多的空间.因为这些空间实在栈上申请的(如果是局部变量),栈的空间是有限的并且是宝贵的,所以呢,开辟太多的空间而不适用很可能会 ...

  9. String类的常用方法

    package stringUse; public class StringUse { public static void main(String[] args) { //获取 //indexOf, ...

  10. Nutch的配置以及动态网站的抓取

    http://blog.csdn.net/jimanyu/article/details/5619949 一:配置Nutch: 1.解压缩的nutch后,以抓取http://www.163.com/为 ...