说到 shadow-dom 可能很多人会很陌生。但是其实我们肯定碰到过,本文主要想简单介绍下 shadow-dom。下面直接进入正文。

shadow-dom 是什么

顾名思义, shadow-dom,直译的话就是 影子dom ?我觉得可以理解为潜藏在黑暗中的 DOM 结构,也就是我们无法直接控制操纵的 DOM 结构。前端同学经常用开发者工具的话,查看 DOM 结构的时候,肯定看到过下面这样的结构:

这里的 #shadow-root 所包含的内容其实就是所谓的 shadow-dom 。

shadow-dom 其实是浏览器的一种能力,它允许在浏览器渲染文档(document)的时候向其中的 Dom 结构中插入一棵 DOM 元素子树,但是特殊的是,这棵子树(shadow-dom)并不在主 DOM 树中。

举个栗子,也是最常见的例子, <video> 标签,我们创建在页面上创建一个空白的 video 标签:

  1. <video id='test'></video>

查看 DOM 结构如下:

虽然我们创建的是一个空标签,但是在这个空标签内部,存在一个 shadow-dom ,点开 shadow-dom 可以看到内有乾坤,大有内容。其实这内部的具体内容,就是 <video> 的具体实现。

shadow-dom 结构示意

再用一幅图总结一下:

document

这个很好理解,就是我们的正常文档 document 。

shadow host

对于一个内部有 shadow-dom 的元素而言,它必然需要一个宿主元素,对于上面的例子而言, <video> 标签,就是 shadow-dom 的宿主元素。

shadow-root

通过 createShadowRoot(下文会提及) 返回的文档片段被称为 shadow-root 。它和它的后代元素,都将对用户隐藏,但是它们是实际存在的,在 chrome 中,我们可以通常审查元素去查看它们的具体 DOM 实现。

在 <video> 中,例如暂停,播放,音量控制,全屏按钮,进度条等都是 shadow-root 的后代。它们工作时会显示在屏幕上,但他们的 DOM 结构对用户是不可见的。

contents

就是上述所说的 <video> 中各子组件的 DOM 的具体实现。

为什么需要 shadow-dom

为什么需要有这种结构呢?

Shadow-dom 是游离在 DOM 树之外的节点树,但是他的创建基于普通 DOM 元素(非 document),并且创建后的 Shadow-dom 节点可以从界面上直观的看到。更重要的是,Shadow-dom 具有良好的密封性。

这是浏览器提供的一种“封装”功能,提供了一种强大的技术去隐藏一些实现细节。什么意思呢?以 w3c 上的一个 <video> 例子为例,我们仅仅是填写了一个空白的标签,再加上 src 属性里填上视频地址,就可以播放视频了:

我们仅仅填写了一行代码,却拥有比这行代码更多的功能,譬如暂停,播放,音量控制,全屏按钮,进度条等等。

这些功能具体的 DOM 实现,其实都在 shadow-dom 中:

浏览器的开发者们意识到作为前端开发者,引用一个 <video> 标签的时候,每次还要写入一大堆 DOM 去控制控件的表现和行为,既不简洁也很困难。所以他们界定了这样一个界限,界定了哪些是你可以访问的,哪些实现细节是访问不到的。

那些不希望我们访问到的细节,则封装在了 shadow-dom 中。然而,浏览器本身却可以随意跨越这个边界。设置这样一个边界之后,浏览器的开发者们就可以在我们看不见的地方使用熟悉的web技术、同样的HTML元素去创建更多的功能,而不是像我们一样要在页面上用div和span来堆砌这些元素。

如何控制 shadow-dom

既然是浏览器开发者有意隐藏起来的 DOM 结构,那么我们是否可以控制内部的 DOM 结构呢?并非完全不可以,还是有一些方法使得我们可以控制 shadow-dom 内的一些表现。

使用伪元素控制 shadow-dom 样式

这里我们要使用到伪元素,通过伪元素,我们可以控制 shadow-dom 中 DOM 结构的样式。

在 chrome 下,查看 shadow-dom 结构(如果无法看到shadow-dom需要手动打开),可以看到每个结点都加上了一个 pesudo 属性:

有了这些属性,我们可以通过伪元素的方式控制他们,譬如在一些场景下 video 标签的控制条不会自动隐藏或自动显示,可以通过伪元素指定默认显隐方式:

如果你在 chrome 浏览器下阅读本文,从上面的 codePen 可以看到,我使用伪元素修改了 video 控件条的底色为粉红色 deeppink。

不幸的是,上面的控制方式只适用于 chrome 浏览器,虽然大部分现代浏览器已经支持 shadow-dom ,但是能够审查 shadow-dom 内部 DOM 元素的只有 chrome 浏览器,其他浏览器仍会把这些细节隐藏。

使用 Javascript 创建一个 shadow-dom 元素

我们也可以通常 Javascript 创建 shadow-dom ,实现各类功能的封装,主要通过:

  1. HTMLElement.prototype.createShadowRoot =
  2. HTMLElement.prototype.createShadowRoot ||
  3. HTMLElement.prototype.webkitCreateShadowRoot ||
  4. function() {};

看看下面这个例子,在chrome内核浏览器下,将创建一个简单的 shadow-dom ,将我们的代码放入一个template 中,再通过 importNode 插入到 shadow-dom 中:

如果你现在在 chrome 内核浏览器下访问本文,那么上述的 codePen 中你应该可以看到 createShadowDomByJs 这一行文字,打开审查元素,会看到 <p> 结构是隐藏在 shadow-dom 中的。

shadow-dom 兼容性

shadow-dom 的未来

本文是非常基本的一些关于 shadow-dom 的概念,只是它的冰山一角,没有十分深入的去研究。

现行的组件都是开放式的,即最终生成的 HTML DOM 结构难以与组件外部的 DOM 进行有效结构区分,样式容易互相混淆。Shadow-dom 的 封装隐藏性为我们提供了解决这些问题的方法。在 Web 组件化的规范中也可以看到 Shadow-dom 的身影,使用具有良好密封性的 Shadow-dom 开发下一代 Web 组件将会是一种趋势。

更多资源及参考文章

如果你读完本文后仍然意犹未尽,可以看看下面这些文章:

到此本文结束,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

神秘的 shadow-dom 浅析的更多相关文章

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

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

  2. 封印术:shadow dom

    置顶文章:<纯CSS打造银色MacBook Air(完整版)> 上一篇:<鼠标滚动插件smoovejs和wowjs> 作者主页:myvin 博主QQ:851399101(点击Q ...

  3. 使用shadow dom封装web组件

    什么是shadow dom? 首先我们先来看看它长什么样子.在HTML5中,我们只用写如下简单的两行代码,就可以通过 <video> 标签来创建一个浏览器自带的视频播放器控件. <v ...

  4. shadow dom

    初识shadow dom 我们先看个input="range"的表现: what amazing ! 一个dom能表现出这么多样式嘛? 无论是初学者和老鸟都是不肯相信的,于是在好奇 ...

  5. shadow dom 隔离代码 封装

    Shadow DOM是指浏览器的一种能力,它允许在文档(document)渲染时插入一棵DOM元素子树,但是这棵子树不在主DOM树中.   Shadow DOM 解决了 DOM 树的封装问题.     ...

  6. 纯CSS菜单样式,及其Shadow DOM,Json接口 实现

    先声明,要看懂这篇博客要求你具备少量基础CSS知识, 当然如果你只是要用的话就随便了,不用了解任何知识 完整项目github链接:https://github.com/git-Code-Shelf/M ...

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

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

  8. Shadow DOM及自定义标签

    参考链接:点我 一.什么是Shadow DOM Shadow DOM,直接翻译的话就是 影子 DOM,可以理解为潜藏在 DOM 结构中并且我们无法直接控制操纵的 DOM 结构.类似于下面这种结构 Sh ...

  9. 理解Shadow DOM(一)

    1. 什么是Shadow DOM? Shadow DOM 如果按照英文翻译的话可以理解为 影子DOM, 何为影子DOM呢?可以理解为一般情况下使用肉眼看不到的DOM结构,那如果一般情况下看不到的话,那 ...

  10. html 中shadow DOM 的使用

    什么是shadow DOM? An important aspect of web components is encapsulation — being able to keep the marku ...

随机推荐

  1. 领域驱动和MVVM应用于UWP开发的一些思考

    领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...

  2. Python高手之路【二】python基本数据类型

    一:数字 int int(整型): 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2147483648-2147483647 在64位系统上,整数的位数为64位,取值 ...

  3. ABP文档 - Javascript Api - Message

    本节内容: 显示信息 确认 Message API给用户显示一个信息,或从用户那里获取一个确认信息. Message API默认使用sweetalert实现,为使sweetalert正常工作,你应该包 ...

  4. windows环境下sublime的nodejs插件详细安装图解

    前面的话   搜索了好多文档后,才成功地安装了sublime text3的nodejs插件.为了存档,也为了方便有同样需求的朋友,将其安装过程详细记录如下 安装nodejs 虽然nodejs官网提供了 ...

  5. 零OCR基础6行代码实现C#验证码识别

    这两天因为工作需要,要到某个网站采集信息,一是要模拟登陆,二是要破解验证码,本想用第三方付费打码,但是想想网上免费的代码也挺多的,于是乎准备从网上撸点代码下来,谁知道,撸了好多个都不行,本人以前也没接 ...

  6. SQLServer 版本之八大方法搞清 "我是谁"

    你正在使用 SQL Server 的哪个版本? 贴士:作为一个SQL Server数据库管理者或维护.支持人员,应该会经常问自己这样一个问题:我当前SQL Server版本号是?当前版本已经有的累计更 ...

  7. 【C#附源码】数据库文档生成工具支持(Excel+Html)

    [2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...

  8. xss和sql注入原理学习

    8.4 Web跨站脚本攻击 8.4.1  跨站脚本攻击的原理(1) 跨站脚本在英文中称为Cross-Site Scripting,缩写为CSS.但是,由于层叠样式表 (Cascading Style ...

  9. Open-Test 测试驱动模式与版本号管理机制

    以测试用例驱动项目开发,coding/case俩条线并走模式.   1.开发人员只负责功能实现:   2.测试人员提供自测用例,研发人员jenkins持续集成项目后自动化执行自测用例,通过后方可转测试 ...

  10. Linux的locale、LC_ALL和LANG

    如果你是一个Linux新手,并且刚刚安装了一个新的英文系统但想要设置成中文系统,肯定会接触到上面几个变量,在网上搜索了一系列解决方法,给一些变量赋一下值,再export一下,或者写到配置文件里面,然后 ...