英文链接:Shadow DOM: Introduction, 26 AUGUST 2013 on Web Components, Shadow DOM
我们今天要讨论一个有时候十分令人费解的大话题:Shadow DOM。这个话题可能是至少在过去的 5-10 年内前端开发最具有革命性的新技术之一。由于太过宏大,一篇博文不足以蔽之,我决定将其分成一个专题系列,在接下来的几周详尽阐述。
现在让我们用一个总体的介绍来开始这个系列:什么是 Shadow DOM?它为何这么重要?
如果说要用一个例子来解释 Shadow DOM,我认为 <video>
标签最为适合。我们看下下面这个例子:
实例视频
例子视频的 DOM 标签十分的简单:
<video controls autoplay name="media"> <source id="mp4" src="http://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4"> </video>
主要是有一个 <video>
标签包裹着 <source>
标签。但是你仔细想想,这里面其实大有文章。视频播放器本身有播放/暂停按钮、进度条、视频时间显示、音量控制以及播放时的一个全屏切换按钮。既然 DOM 源码这么干净,那实现这些组件的代码是从哪儿来的呢?
事实上,各大浏览器的厂商已经编写了播放器的组件代码使之能够正常运作。如果你打开 Chrome 的开发者工具,点击右上角的“Settings”按钮,
勾选“Show user agent shadow DOM”,
你就可以看到视频播放器 DOM 结构的细节。
看到标灰的 #shadow-root
了吗?这里就是所有视频播放器控制组件的所在之处。浏览器之所以将其置灰,是为了表明这部分是在 shadow DOM 里,对于页面的其他部分来说它是不可用的。这里的不可用意味着你写的 CSS 选择器和 JavaScript 代码都不会影响到这部分内容。实际上,让 <video>
标签的 UI 能够运行的标签和样式都被浏览器封装了。
那么,什么是 Shadow DOM 呢?
简而言之,Shadow DOM 是一个 HTML 的新规范,其允许开发者封装自己的 HTML 标签、CSS 样式和 JavaScript 代码。Shadow DOM 以及我们以后将会讨论的一些技术,使得开发人员可以创建诸如 <video>
这样自定义的一级标签。总的来说,这些新标签和相关的 API 被称为 Web Components。
如果你已经做过一段时间的网站开发,你可能听过 Bootstrap。Bootstrap 是一组 UI 组件的集合,使用它需要将一系列 CSS 样式、JS 脚本以及规定的 HTML 模式糅合在一起。以下这个例子展示了使用 Bootstrap navabar 所需要编写的 HTML 结构:
<nav class="navbar navbar-default navbar-fixed-top" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex6-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Brand</a> </div> <div class="collapse navbar-collapse navbar-ex6-collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Contact</a></li> </ul> </div> </nav>
由于无法封装 Boostrap 的组件,因此你自己的 HTML 必须要和它文档上的保持一致。很多时候这就意味着你要从 Boostrap 的说明文档里把这一坨代码复制过来然后粘贴到你的项目中。尽管用这种方法也可以快速的构建页面,但这也意味着大部分的页面标签都不是你自己写的,你也没有深入了了解这些页面结构。这可能会导致各种潜在的小 bug,你也无法快速直观的分析自己的工作——因为你代码里都是一坨又一坨的模板。
再考虑一下这个情况:Boostrap 的 CSS 样式表有大约 6600 行那么多,这就意味着任何时候你都有可能一个不小心覆盖了一个至关重要的选择器,导致页面一部分样式崩坏。你的 JavaScript 代码也需要和 Bootstrap 的 JavaScript 代码共存,同时要小心的遵守它的使用方式,而不能擅自变更。
要整的事儿太多了……
额,当然,以上的这一堆麻烦事儿也会同样发生在你在程序里要引入的任何第三方 jQuery 插件、动画引擎、图表库、模块管理等各种组件中……
让我们想象一下,如果在上一个例子中, Boostrap 的 navbar 的用法像 <video>
标签一样,它可能看起来是这样:
<bootstrap-navbar fixed-top> <a href="#">Home</a> <a href="#">About</a> <a href="#">Contact</a> </bootstrap-navbar>
这样是不是看起来简洁多了~
直到最近(此文成文时间是 2013 年 8 月份)这种事情都是不可能实现的。当然你可以在 HTML 里定义自己的标签,但是浏览器会把不认识的标签全当做 <div>
处理,同时你这么写也得不到任何特殊的带有封装特性的好处。更重要的是,你无法把 navbar 的实现细节隐藏起来,实现的代码必须存在于页面某处。如果你真的想实现一些私有化,你必须使用臃肿无比又难以处理的 <iframe>
。Shadow DOM 的引入改变了这一切。
我确信你已经厌倦了我的闲扯,准备码上一战了~随我去下一篇博文,我们会深入探讨一下 Shadow DOM 并漫谈一下它的基础知识。