1. 首页

你好,请问Shadow DOM是什么?

几周前,我写了一篇关于究竟是什么DOM的文章。回顾一下,文档对象模型是HTML文档的表示。浏览器使用它来确定页面上要呈现的内容,并通过Javascript程序来修改页面的内容,结构或样式。

例如,让我们采用以下HTML文档:


<!doctype html> <html lang="en"> <head> <title>My first web page</title> </head> <body> <h1>Hello, world!</h1> <p>How are you?</p> </body> </html>

上面的HTML文档将产生以下DOM树。

  • html
    • head
      • title
        • My first web page
    • body
      • h1
        • Hello, world!
      • p
        • How are you?

在过去几年中,您可能听说过“Shadow DOM”和“Virtual DOM”等术语。这些虽然当然与原始DOM有关,但它们指的是截然不同的概念。在本文中,我将详细介绍Shadow DOM以及它与原始DOM的区别。在以后的文章中,我将对虚拟DOM进行分析。

一切都是 global 的??!等等,一切都是 global 的??

HTML文档中的所有元素和样式以及DOM都位于一个全局范围内。页面上的任何元素都可以通过document.querySelector()方法访问,无论它在文档中的嵌套程度如何或放置在何处。同样,应用于文档的CSS可以选择任何元素,无论它在何处。

当我们想要将样式应用于整个文档时,可以直接使用*选择页面上的每个元素并将它们的盒模型进行修改。box-sizing


* { box-sizing: border-box }

另一方面,有些时候元素需要完全封装,我们不希望它受到全局样式的影响。一个很好的例子是第三方小部件,例如Twitter的“关注”按钮。以下是该小部件的示例:

Follow @ireaderinokun

Twitter follow @ireaderinokun

假设您启用了Javascript并且检查了元素,您会注意到该按钮是一个<iframe>元素,您实际看到的样式按钮其实是加载一个小文档。

Follow-button-widget-iframe

这是Twitter可以确保其小部件的预期样式不受文档中的任何CSS影响的唯一方式。尽管有一些方法可以使用级联来尝试实现相同的结果,但是没有其他方法可以提供与<iframe>相同的效果。

创建Shadow DOM是为了允许在Web平台上本地封装和组件化,而不必依赖像<iframe>这样的工具,而这些工具实际上并不是为此目的而制作的。

DOM中的DOM

您可以将shadow DOM视为“DOM中的DOM”。它是自己独立的DOM树,具有自己的元素和样式,与原始DOM完全隔离。

虽然最近才指定供Web作者使用,但用户代理多年来一直使用shadow DOM来创建和设置复杂组件(如表单元素)。我们来看一下input。要在页面上创建一个,我们所要做的就是添加以下元素:


<input type="range">

如果我们深入挖掘,我们会看到这个<input>元素实际上是由几个较小的<div>元素组成,控制着轨道和滑块本身。

Range input shadow dom

这是使用shadow DOM实现的。暴露给主机HTML的元素记录了简单的<input>,但在其下面有与组件相关的元素和样式,它们不构成DOM全局​​范围的一部分。

shadow DOM如何工作

为了说明shadow DOM的工作原理,让我们使用shadow DOM而不是<iframe>来重新创建Twitter“follow”按钮。

首先,我们从shadow host开始。这是我们想要将新影子DOM附加到原始DOM中的常规HTML元素。对于像Follow按钮这样的组件,它还可以包含我们希望在页面上未启用Javascript或不支持shadow DOM时显示的回退元素。


<span class="shadow-host"> <a href="https://twitter.com/ireaderinokun"> Follow @ireaderinokun </a> </span>

Js中文网 – 前端进阶资源教程 www.javascriptC.com,typescript 中文文档
一个帮助开发者成长的社区,你想要的,在这里都能找到

请注意,我们不仅仅使用<a>元素作为dow host,因为某些元素(主要是交互元素)不能是dow host。

要将阴影DOM附加到我们的主机,我们使用attachShadow()方法。


const shadowEl = document.querySelector(".shadow-host"); const shadow = shadowEl.attachShadow({mode: 'open'});

这将创建一个空的shadow root作为我们的shadow host的子项。shadow root 是新的shadow DOM的开始,其方式是<html>元素是原始DOM的开头。我们可以通过#shadow-root 在devtools检查器中看到我们的shadow-root。

Empty shadow root

虽然常规HTML子项在检查器中是可见的,但是当shadow root接管时,它们在页面上不再可见。

接下来,我们要创建内容以形成新的shadow tree。shadow tree就像一个DOM树,但是对于shadow DOM而不是常规DOM。要创建我们的跟随按钮,我们所需要的只是一个新的<a>元素,它与我们已有的后备链接几乎完全相同,但带有一个图标。


const link = document.createElement("a"); link.href = shadowEl.querySelector("a").href; link.innerHTML = <span aria-label="Twitter icon"></span> ${shadowEl.querySelector("a").textContent} ;

我们将这个新元素添加到我们的shadow DOM中,就像使用appendChild()方法将任何元素作为子元素添加到另一个元素一样。


shadow.appendChild(link);

在这一点上,这是我们的元素的样子:

Plain text of "Follow-@ireaderinokun"

最后,我们可以通过创建一个<style>元素并将其附加到阴影根来添加一些样式。

Js中文网 – 前端进阶资源教程 www.javascriptC.com,typescript 中文文档
一个帮助开发者成长的社区,你想要的,在这里都能找到


const styles = document.createElement("style"); styles.textContent = a, span { vertical-align: top; display: inline-block; box-sizing: border-box; } a { height: 20px; padding: 1px 8px 1px 6px; background-color: #1b95e0; color: #fff; border-radius: 3px; font-weight: 500; font-size: 11px; font-family:'Helvetica Neue', Arial, sans-serif; line-height: 18px; text-decoration: none; } a:hover { background-color: #0c7abf; } span { position: relative; top: 2px; width: 14px; height: 14px; margin-right: 3px; background: transparent 0 0 no-repeat; background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2072%2072%22%3E%3Cpath%20fill%3D%22none%22%20d%3D%22M0%200h72v72H0z%22%2F%3E%3Cpath%20class%3D%22icon%22%20fill%3D%22%23fff%22%20d%3D%22M68.812%2015.14c-2.348%201.04-4.87%201.744-7.52%202.06%202.704-1.62%204.78-4.186%205.757-7.243-2.53%201.5-5.33%202.592-8.314%203.176C56.35%2010.59%2052.948%209%2049.182%209c-7.23%200-13.092%205.86-13.092%2013.093%200%201.026.118%202.02.338%202.98C25.543%2024.527%2015.9%2019.318%209.44%2011.396c-1.125%201.936-1.77%204.184-1.77%206.58%200%204.543%202.312%208.552%205.824%2010.9-2.146-.07-4.165-.658-5.93-1.64-.002.056-.002.11-.002.163%200%206.345%204.513%2011.638%2010.504%2012.84-1.1.298-2.256.457-3.45.457-.845%200-1.666-.078-2.464-.23%201.667%205.2%206.5%208.985%2012.23%209.09-4.482%203.51-10.13%205.605-16.26%205.605-1.055%200-2.096-.06-3.122-.184%205.794%203.717%2012.676%205.882%2020.067%205.882%2024.083%200%2037.25-19.95%2037.25-37.25%200-.565-.013-1.133-.038-1.693%202.558-1.847%204.778-4.15%206.532-6.774z%22%2F%3E%3C%2Fsvg%3E); } ; shadow.appendChild(styles);

这是我们的最后一个要素:

Follow @ireaderinokun Twitter follow @ireaderinokun

DOM与shadow DOM

在某些方面,shadow DOM是DOM的“精简”版本。与DOM一样,它是HTML元素的表示,用于确定在页面上呈现的内容并启用元素的修改。但与DOM不同,shadow DOM不是基于完整的独立文档。正如其名称所示,shadow DOM始终附加到常规DOM中的元素。没有DOM,shadow DOM就不存在了。

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文来源于网络,其版权属原作者所有,如有侵权,请与小编联系,谢谢!

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:你好,请问Shadow DOM是什么?

链接:https://www.javascriptc.com/1950.html

原文链接:https://www.zcfy.cc/article/what-is-the-shadow-dom

« 玩转CSS 与 JS 动画的底层机制 之 如何优化它们的性能篇
优秀的攻城狮都如何使用JavaScript数组的?»
Flutter 中文教程资源

相关推荐

QR code