在我的项目中实现 Shadow DOM 是否会让它们像 React 使用的虚拟 DOM 一样更快?
2 回答
虚拟 DOM
虚拟 DOM 旨在避免对 DOM 进行不必要的更改,这在性能方面是昂贵的,因为对 DOM 的更改通常会导致页面重新呈现。虚拟 DOM 还允许一次收集要应用的多个更改,因此并非每个更改都会导致重新渲染,而是仅在将一组更改应用于 DOM 后才发生一次重新渲染。
影子 DOM
Shadow dom 主要是关于实现的封装。单个自定义元素可以实现或多或少复杂的逻辑与或多或少复杂的 DOM 相结合。可以通过导入将任意复杂度的整个 Web 应用程序添加到页面中,<body><my-app></my-app>
但也可以将更简单的可重用和可组合组件实现为自定义元素,其中内部表示隐藏在影子 DOM 中,如<date-picker></date-picker>
.
样式封装 Shadow DOM 还可以防止样式被意外应用到设计者不打算使用的元素,例如,因为您使用的 CSS 或组件库更改了一个选择器,该选择器现在适用于使用相同 CSS 类名的其他元素。添加到组件的样式的范围仅限于该组件,并且可以防止样式流出或流入。
Shadow DOM 和性能
尽管 shadow DOM 首先与性能无关,但它也对性能有影响。因为样式是有范围的,浏览器可以假设某些更改仅影响页面的有限区域(自定义元素的影子 DOM),这可以限制重新渲染到此类组件的区域,而不是重新渲染整个页面。
这就是允许跨阴影 DOM 边界应用样式的、 和CSS 组合器被弃用的原因>>>
,并且很快就会从 Chrome 中删除(其他浏览器从未有过它们的 AFAIK)。这些组合器的存在阻止了上一段中提到的那种优化。/deep/
::shadow
Angular2使用了这两个世界的优点。
它使用单向数据流并仅在模型上运行更改检测。如果它检测到更改,它会通过更新绑定来更新 DOM,并使结构指令如*ngFor
, *ngIf
, ... 更新 DOM。因此,仅当模型实际更改时才更新 DOM。
Angular2 使用 shadow DOM(ViewEncapsulation.Native
目前不是默认的)来利用浏览器提供的样式封装功能,或者(当前默认)只是通过重写添加到组件的样式来模拟样式封装,作为一种解决方法,直到原生 shadow DOM 和 CSS 变量(用于动态全局样式更改)变得广泛可用。
不,Shadow DOM 和 Virtual DOM 是无关的,尽管名称有些相似:
Virtual DOM:出于不同的原因,保留两个 DOM 副本(原始的和更新的)的 React 概念。在渲染之前,React 对这两个对象进行比较以确定它是否应该对实际的 DOM 树应用更新。这会提高性能,因为我们只更新需要它的视图部分,而不是整个屏幕。
Shadow DOM: W3C 提出的Web Components 规范的一部分,它基本上允许将较小的 DOM 元素和 CSS 样式封装到单个 DOM 元素中:
示例 Shadow DOM 元素
<my-video width="300" height="150" />
但是,<my-video>
实际上封装了以下元素:
<div>
<input type="button" style="color: blue;">Play
<input type="button" style="color: red;">Pause
<source src="myVideo.mp4">
</div>
因此,通过使用 Shadow DOM,我们能够隐藏 Web 元素的实现细节,并且只将必要的信息传递给子元素(即height
, width
),这可能令人困惑,这与 ReactJS 传递props
给组件的习惯用法非常相似.
通过以下方式提供的信息: