需要帮助了解阴影 DOM

Need help understanding the Shadow DOM

阅读有关 Shadow 的文章和教程 DOM,我发现了一个让我有点困惑的描述:

"Shadow DOM refers to the ability of the browser to include a subtree of DOM elements into the rendering of a document, but not into the main document DOM tree."

所以 Shadow 树不是 DOM 树的一部分?但是浏览器仍然会看到它并呈现它的内容?

这句话似乎来自这篇标题为:What the Heck is Shadow DOM?

的文章

阴影 DOM 是 DOM 的 部分(但是虚拟 DOM 是 [=76= 的隐藏副本]. 很抱歉之前与虚拟 DOM!) 的混淆。再次查看此 W3 Spec 后,影子 DOM 似乎只是一个可重复使用的 DOM 片段。浏览器会看到它并呈现它的内容。

This specification describes a method of combining multiple DOM trees into one hierarchy and how these trees interact with each other within a document, thus enabling better composition of the DOM.

这项技术至少从 2006 年开始就存在,当时我开始在 JavaScript 中使用 .innerHTML 和模板来构建可重用的 DOM 片段。这不是新技术。它只是在 2015 年被 W3C 记录为官方规范。

有趣的是这些 CSS 属性和 pseudo-selectors,它们在阴影 DOM 上运行,但不是真实 DOM 的一部分。它们在 W3 Spec.

组合树部分 的底部进行了描述

::shadow pseudo element

/deep/ combinator, which was replaced with a >>> combinator (or shadow piercing descendant combinator)

::content pseudo-element

:host pseudo-class and :host() functional pseudo-class

:host-context() functional pseudo-class

它们有点添加到这些选择器中,人们有时会使用这些选择器来创建 <div> 标签,其中 carets/pointers 到其他 on-screen 元素:

::before & ::after

补充更新:

我在 Shadow DOM 101 link 找到了更多详细信息。查看 "Hello my name is Bob... Shellie" 示例(页面下方约 1/2)时,它位于此文本块的正上方...

Now we have achieved separation of content and presentation. The content is in the document; the presentation is in the Shadow DOM. They are automatically kept in sync by the browser when it comes time to render something.

...我们可以检查 DOM 并查看阴影 DOM 的样子。看起来像这样,其中 CSS 和 HTML 都可以封装在 "shadow DOM" 元素中,该元素隐藏在 <div> 标签中。参见:https://developer.chrome.com/devtools/docs/settings-files/show-shadow-dom.png

似乎这个想法是封装 CSS 和 HTML,这样它就不会溢出到页面的其他区域。也不允许其他现有的 / on-page 代码影响该封装代码块内部的内容。这种封装的较早示例将隐藏 <iframe> 标签,该标签旨在显示广告但阻止第 3 方广告代码破坏我们非常酷的网页上的 JS。

这里还有一些影子DOM links:

  1. Shadow DOM 101
  2. Shadow DOM 201
  3. Shadow DOM 301
  4. Visualizing Shadow DOM Concepts

根据 Shadow DOM 规范,

A document tree is a node tree whose root node is a document.

Any element can host zero or one associated node trees, called a shadow tree.

A shadow host is an element that hosts one shadow tree.

A shadow root is the root node of a shadow tree.

A tree of trees is a tree of node trees.

那么,是的,阴影树在文档树之外,但它们仍然链接在一起形成树中树。

是的,渲染阴影内容而不是元素的后代,如 CSS Scoping:

中所定义

The most recently-created shadow tree on an element is the active shadow tree for that element.

The descendants of a shadow host must not generate boxes in the formatting tree. Instead, the contents of the active shadow tree generate boxes as if they were the contents of the element instead.

我认为理解影子的最简单方法 DOM 是通过示例:

<div>
  <input type="range">
</div>

您的上述代码 DOM 将完全符合您的预期:

div
- input[type=range]

但是您的浏览器呈现的是其他东西:有一条水平线和一个拇指(或旋钮或任何您称之为的东西)。所以在内部,input 有一些子元素,但它们不会通过 DOM:

暴露出来
div
- input[range]
  - bar
  - thumb

但是正如我已经写过的那样:那些没有通过 DOM 暴露出来,所以它们对你、你的 CSS、你的 JS 是隐藏的(这不完全正确,浏览器可以给你某些访问权限,例如基于 Webkit 的浏览器允许您通过 -webkit-slider-thumb 伪元素在 CSS 中操纵缩略图的外观。

另一方面,这些元素需要位于 DOM 某处才能由浏览器呈现,这就是影子 DOM 出现的地方:在内部,浏览器会替换input[type=range]在DOM树旁

input[range]
- bar
- thumb

这就是阴影 DOM:某些元素是某些元素的子元素,不是因为您将它们放在 HTML 中,而是因为父元素被定义为具有这些子元素(例如音频元素被定义为有一个播放按钮)并且不会通过 DOM 公开,而是由浏览器在内部生成。

可以在此处找到更多示例和更详尽的解释:What the Heck is Shadow DOM?