在我的项目中实现Shadow DOM是否会像React所使用的虚拟DOM一样使它们更快?
Answers:
虚拟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类名的其他元素。添加到组件的样式的作用域仅限于该组件,可以防止样式渗出或渗入。
影子DOM和性能
即使影子DOM最初与性能无关,它也具有性能影响。因为样式是作用域的,所以浏览器可以对某些更改做出假设,以仅影响页面的有限区域(自定义元素的阴影DOM),从而可以将重新呈现限制为此类组件的区域,而不是重新呈现整个页面。
这就是原因>>>
,/deep/
和::shadow
CSS组合程序,这使得跨影子DOM边界应用样式,已过时,受到从Chrome很快删除(其他浏览器永远得不到据我所知)。这些组合器的存在阻碍了上一段中提到的优化。
Angular2利用了两个世界的优势。
它使用单向数据流,并且仅在模型上运行更改检测。如果检测到变化它会导致DOM被更新的绑定更新,并作出这样结构的指令*ngFor
,*ngIf
...更新DOM。因此,仅在实际更改模型时才更新DOM。
Angular2使用影子DOM(ViewEncapsulation.Native
目前不是默认值)来利用浏览器提供的样式封装功能,或者(当前默认)是通过重写添加到组件的样式来模拟样式封装,作为一种解决方法,直到本机影子DOM和CSS变量(用于动态全局样式更改)变得广泛可用。
不,Shadow DOM和Virtual DOM是无关的,尽管它们的名称有些类似:
虚拟DOM: React概念,出于差异原因,保留DOM的两个副本(原始副本和更新副本)。在渲染之前,React对两个对象进行区分,以确定是否应将更新应用于实际的DOM树。这将提高性能,因为我们仅更新视图中需要它的部分,而不是整个屏幕。
Shadow DOM: W3C提出的Web组件规范的一部分,该规范基本上允许将较小的DOM元素和CSS样式封装到单个DOM元素中:
阴影DOM元素示例
<video width="300" height="150" />
但是,<video>
实际上封装了以下元素:
<div>
<input type="button" style="color: blue;">Play
<input type="button" style="color: red;">Pause
<source src="myVideo.mp4">
</div>
因此,通过使用影子DOM,我们能够隐藏我们的Web元素的实现细节,只沿必要的信息传递到子元素(即height
,width
),这或许令人混淆,外观极像ReactJS成语传球props
到组件。
通过以下方式提供的信息:
<video>
)之后,但是并没有提高性能的期望。