它们是用于不同目的的不同事物,因此比较性能没有意义。
虚拟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),这可以将重新渲染限制在此类组件的区域,而不是重新渲染整个页面。
这就是原因>>>
, /deep/
, and ::shadow
CSS 组合器允许跨影子 DOM 边界应用样式,但已被弃用,并且很快就会从 Chrome 中删除(据我所知,其他浏览器从未拥有过它们)。这些组合器的存在本身就阻止了上一段提到的优化。
Angular2利用两个世界的优势。
它使用单向数据流并仅对模型运行更改检测。如果它检测到更改,它会导致 DOM 通过更新绑定来更新,并制定结构指令,例如*ngFor
, *ngIf
, ...更新 DOM。因此,DOM 仅在模型实际更改时更新。
Angular2 使用 Shadow DOM(仅适用于ViewEncapsulation.Native
(当前不是默认设置)利用浏览器提供的样式封装功能,或者(当前默认设置)仅通过重写添加到组件的样式来模拟样式封装,作为本地影子 DOM 和 CSS 变量(用于动态全局样式更改)之前的解决方法变得广泛可用。