神秘的 shadow-dom 浅析
说到 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
标签:
- <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
,实现各类功能的封装,主要通过:
- HTMLElement.prototype.createShadowRoot =
- HTMLElement.prototype.createShadowRoot ||
- HTMLElement.prototype.webkitCreateShadowRoot ||
- 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 浅析的更多相关文章
- 【shadow dom入UI】web components思想如何应用于实际项目
回顾 经过昨天的优化处理([前端优化之拆分CSS]前端三剑客的分分合合),我们在UI一块做了几个关键动作: ① CSS入UI ② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀 ...
- 封印术:shadow dom
置顶文章:<纯CSS打造银色MacBook Air(完整版)> 上一篇:<鼠标滚动插件smoovejs和wowjs> 作者主页:myvin 博主QQ:851399101(点击Q ...
- 使用shadow dom封装web组件
什么是shadow dom? 首先我们先来看看它长什么样子.在HTML5中,我们只用写如下简单的两行代码,就可以通过 <video> 标签来创建一个浏览器自带的视频播放器控件. <v ...
- shadow dom
初识shadow dom 我们先看个input="range"的表现: what amazing ! 一个dom能表现出这么多样式嘛? 无论是初学者和老鸟都是不肯相信的,于是在好奇 ...
- shadow dom 隔离代码 封装
Shadow DOM是指浏览器的一种能力,它允许在文档(document)渲染时插入一棵DOM元素子树,但是这棵子树不在主DOM树中. Shadow DOM 解决了 DOM 树的封装问题. ...
- 纯CSS菜单样式,及其Shadow DOM,Json接口 实现
先声明,要看懂这篇博客要求你具备少量基础CSS知识, 当然如果你只是要用的话就随便了,不用了解任何知识 完整项目github链接:https://github.com/git-Code-Shelf/M ...
- JavaScript 是如何工作:Shadow DOM 的内部结构 + 如何编写独立的组件!
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 17 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...
- Shadow DOM及自定义标签
参考链接:点我 一.什么是Shadow DOM Shadow DOM,直接翻译的话就是 影子 DOM,可以理解为潜藏在 DOM 结构中并且我们无法直接控制操纵的 DOM 结构.类似于下面这种结构 Sh ...
- 理解Shadow DOM(一)
1. 什么是Shadow DOM? Shadow DOM 如果按照英文翻译的话可以理解为 影子DOM, 何为影子DOM呢?可以理解为一般情况下使用肉眼看不到的DOM结构,那如果一般情况下看不到的话,那 ...
- html 中shadow DOM 的使用
什么是shadow DOM? An important aspect of web components is encapsulation — being able to keep the marku ...
随机推荐
- 领域驱动和MVVM应用于UWP开发的一些思考
领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...
- Python高手之路【二】python基本数据类型
一:数字 int int(整型): 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2147483648-2147483647 在64位系统上,整数的位数为64位,取值 ...
- ABP文档 - Javascript Api - Message
本节内容: 显示信息 确认 Message API给用户显示一个信息,或从用户那里获取一个确认信息. Message API默认使用sweetalert实现,为使sweetalert正常工作,你应该包 ...
- windows环境下sublime的nodejs插件详细安装图解
前面的话 搜索了好多文档后,才成功地安装了sublime text3的nodejs插件.为了存档,也为了方便有同样需求的朋友,将其安装过程详细记录如下 安装nodejs 虽然nodejs官网提供了 ...
- 零OCR基础6行代码实现C#验证码识别
这两天因为工作需要,要到某个网站采集信息,一是要模拟登陆,二是要破解验证码,本想用第三方付费打码,但是想想网上免费的代码也挺多的,于是乎准备从网上撸点代码下来,谁知道,撸了好多个都不行,本人以前也没接 ...
- SQLServer 版本之八大方法搞清 "我是谁"
你正在使用 SQL Server 的哪个版本? 贴士:作为一个SQL Server数据库管理者或维护.支持人员,应该会经常问自己这样一个问题:我当前SQL Server版本号是?当前版本已经有的累计更 ...
- 【C#附源码】数据库文档生成工具支持(Excel+Html)
[2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...
- xss和sql注入原理学习
8.4 Web跨站脚本攻击 8.4.1 跨站脚本攻击的原理(1) 跨站脚本在英文中称为Cross-Site Scripting,缩写为CSS.但是,由于层叠样式表 (Cascading Style ...
- Open-Test 测试驱动模式与版本号管理机制
以测试用例驱动项目开发,coding/case俩条线并走模式. 1.开发人员只负责功能实现: 2.测试人员提供自测用例,研发人员jenkins持续集成项目后自动化执行自测用例,通过后方可转测试 ...
- Linux的locale、LC_ALL和LANG
如果你是一个Linux新手,并且刚刚安装了一个新的英文系统但想要设置成中文系统,肯定会接触到上面几个变量,在网上搜索了一系列解决方法,给一些变量赋一下值,再export一下,或者写到配置文件里面,然后 ...