浏览器原理 25 # 虚拟DOM和实际的DOM有何不同?

简介: 浏览器原理 25 # 虚拟DOM和实际的DOM有何不同?

说明

浏览器工作原理与实践专栏学习笔记



DOM 的缺陷

操作 DOM 触发样式计算、布局、绘制、栅格化、合成等任务,还有可能引起重绘或者合成操作。另外,对于 DOM 的不当操作还有可能引发强制同步布局和布局抖动的问题,这些操作都会大大降低渲染效率。


什么是虚拟 DOM


虚拟 DOM 要解决什么事情


将页面改变的内容应用到虚拟 DOM 上,而不是直接应用到 DOM 上。


变化被应用到虚拟 DOM 上时,虚拟 DOM 并不急着去渲染页面,而仅仅是调整虚拟 DOM 的内部状态,这样操作虚拟 DOM 的代价就变得非常轻了。


在虚拟 DOM 收集到足够的改变时,再把这些变化一次性应用到真实的 DOM 上。


虚拟 DOM 执行流程


结合 React 流程画的一张虚拟 DOM 执行流程图


20210525204031180.png


创建阶段:首先依据 JSX 和基础数据创建出来虚拟 DOM,它反映了真实的 DOM 树的结构。然后由虚拟 DOM 树创建出真实 DOM 树,真实的 DOM 树生成完后,再触发渲染流水线往屏幕输出页面。


更新阶段:如果数据发生了改变,那么就需要根据新的数据创建一个新的虚拟 DOM 树;然后 React 比较两个树,找出变化的地方,并把变化的地方一次性更新到真实的 DOM 树上;最后渲染引擎更新渲染流水线,并生成新的页面。



React Fiber 更新机制

通过上图可以知道,当有数据更新时,React 会生成一个新的虚拟 DOM,然后拿新的虚拟 DOM 和之前的虚拟 DOM 进行比较,这个过程会找出变化的节点,然后再将变化的节点应用到 DOM 上。


重点关注下比较过程,最开始的时候,比较两个虚拟 DOM 的过程是在一个递归函数里执行的,其核心算法是 reconciliation。通常情况下,这个比较过程执行得很快,不过当虚拟 DOM 比较复杂的时候,执行比较函数就有可能占据主线程比较久的时间,这样就会导致其他任务的等待,造成页面卡顿。为了解决这个问题,React 团队重写了 reconciliation 算法,新的算法称为 Fiber reconciler,之前老的算法称为 Stack reconciler。


关于协程可以看看之前的笔记:浏览器原理 19 # JavaScript 引擎是如何实现 async / await 以同步的方式来编写异步代码的?


协程的另外一个称呼就是 Fiber,所以在这里我们可以把 Fiber 和协程关联起来,那么所谓的 Fiber reconciler 就是在执行算法的过程中出让主线程,这样就解决了 Stack reconciler 函数占用时间过久的问题。



双缓存视角看虚拟 DOM

比如:一幅完整的画面,可能需要计算多次才能完成,如果每次计算完一部分图像,就将其写入缓冲区,那么就会造成一个后果,那就是在显示一个稍微复杂点的图像的过程中,你看到的页面效果可能是一部分一部分地显示出来,因此在刷新页面的过程中,会让用户感受到界面的闪烁。


而使用双缓存,可以让你先将计算的中间结果存放在另一个缓冲区中,等全部的计算结束,该缓冲区已经存储了完整的图形之后,再将该缓冲区的图形数据一次性复制到显示缓冲区,这样就使得整个图像的输出非常稳定。


双缓存是一种经典的思路,应用在很多场合,能解决页面无效刷新和闪屏的问题,虚拟 DOM 就是双缓存思想的一种体现。你可以把虚拟 DOM 看成是 DOM 的一个 buffer,和图形显示一样,它会在完成一次完整的操作之后,再把结果应用到 DOM 上,这样就能减少一些不必要的更新,同时还能保证 DOM 的稳定输出。


MVC 模式中虚拟 DOM 所扮演的角色


MVC 是一个非常重要且应用广泛的模式,因为它能将数据和视图进行分离,在涉及到一些复杂的项目时,能够大大减轻项目的耦合度,使得程序易于维护。


MVC 的基础结构:

20210525213442594.png



MVC 的整体结构比较简单,由模型、视图和控制器组成,其核心思想就是将数据和视图分离,也就是说视图和模型之间是不允许直接通信的,它们之间的通信都是通过控制器来完成的。


基于 React 和 Redux 构建 MVC 模型:


20210525214021165.png



在该图中,可以把虚拟 DOM 看成是 MVC 的视图部分,其控制器和模型都是由 Redux 提供的。

其具体实现过程如下:


   图中的控制器是用来监控 DOM 的变化,一旦 DOM 发生变化,控制器便会通知模型,让其更新数据;


   模型数据更新好之后,控制器会通知视图,告诉它模型的数据发生了变化;


   视图接收到更新消息之后,会根据模型所提供的数据来生成新的虚拟 DOM;


   新的虚拟 DOM 生成好之后,就需要与之前的虚拟 DOM 进行比较,找出变化的节点;


   比较出变化的节点之后,React 将变化的虚拟节点应用到 DOM 上,这样就会触发 DOM 节点的更新;


   DOM 节点的变化又会触发后续一系列渲染流水线的变化,从而实现页面的更新。


分析基于 React 或者 Vue 这些前端框架时,先重点把握大的 MVC 骨架结构,然后再重点查看通信方式和控制器的具体实现方式。



拓展


其实虚拟 DOM 主要是一个抽象层,用于描述视图,抽象视图变化,诞生主要目的是跨平台。所以才有 React Native,weex。解决 js 操作 dom 性能问题只是附带的,而且虚拟 DOM 是有代价的,在页面结构简单操作也简单的情况下相对 js 操作 DOM 并不一定会有优势。


另外感兴趣的可以看:


snabbdom


可以看一下这篇文章:Virtual Dom库snabbdom代码解析


可以从下面三个方向稍微了解一下 snabbdom


   第一个是js模拟的dom节点vnode的结构


   第二个是diff算法


   第三个是有了diff如何打patch的








目录
相关文章
|
18天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
不同浏览器在解析XML DOM时存在差异,尤其是在处理空白和换行方面。W3C DOM规范虽被广泛支持,但例如,Internet Explorer不将空白或换行视为文本节点,而其他浏览器则会。示例中,一个XML文档在元素间有换行和空格,IE识别为4个子节点,而其他浏览器识别为9个。代码通过loadXMLDoc加载XML并输出子节点数量来展示这一差异。
|
2天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
现代浏览器均支持W3C DOM规范,但存在处理空白和换行的差异。例如,XML文档中的换行和空格可能作为文本节点被其他浏览器识别,但Internet Explorer不会。示例代码显示,加载XML文件后,不同浏览器计算根元素子节点数量的结果不同,IE显示4个,而其他浏览器显示9个。
|
2天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
不同浏览器在解析XML DOM时存在差异,尤其是对待空白和换行的方式。当XML文档中包含换行和空格时,Internet Explorer不会将它们视为文本节点,而其他浏览器则会。例如,一个XML文档在简单编辑器中可能有CR/LF和空格,导致在IE中根元素有4个子节点,但在其他浏览器中有9个子节点。示例代码通过加载XML文件并输出子节点数量来展示这一差异。
|
4天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
现代浏览器虽支持W3C DOM规范,但在处理XML空白和换行时存在差异。IE不将空白或换行视为文本节点,而其他浏览器则会。例如,一个包含CR/LF和空格的XML文档在IE中会有4个子节点,而在其他浏览器中会有9个。示例代码通过加载XML文件并输出子节点数量来展示这一差异。
|
6天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
现代浏览器虽支持W3C DOM规范,但存在处理空白和换行的差异。例如,XML文档中的换行和空格在Internet Explorer中不被视为文本节点,而在其他浏览器中则会。示例代码显示加载"books.xml"后,根元素的子节点数因浏览器不同而异:IE显示4个,其他浏览器显示9个。
|
9天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
现代浏览器虽支持W3C DOM规范,但在处理XML空白和换行时存在差异。IE不将这些空白视为文本节点,而其他浏览器则会。示例显示加载"books.xml"后,根元素的子节点数在IE中显示为4(忽略空白和换行),其他浏览器显示为9(包括空白和换行)。
|
10天前
|
JavaScript 前端开发 网络协议
浏览器的工作原理
主要分为导航、获取数据、HTML解析、css解析、执行javaScript、渲染树几个步骤。
16 1
|
13天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
不同浏览器在解析XML DOM时存在差异,主要关于处理空白和换行。W3C DOM规范被现代浏览器支持,但例如Internet Explorer不将空格或换行视为文本节点,而其他浏览器则会。示例代码展示了一个XML文档,其中包含换行和空格,当获取根元素的子节点数时,IE会输出4,而其他浏览器输出9。
|
18天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
现代浏览器虽支持W3C DOM规范,但在处理XML空白和换行时存在差异。IE不将空格或换行视为文本节点,而其他浏览器则会。例如,一个包含CR/LF和空格的XML文档在IE中会有4个子节点,其他浏览器则有9个。示例代码通过加载XML文件并输出子节点数量来展示这一差异。
|
23天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
不同浏览器在解析XML DOM时存在差异,尤其是对待空白和换行的方式。W3C DOM规范被现代浏览器广泛支持,但例如,Internet Explorer不将空白或换行视为文本节点,而其他浏览器则会。在处理如记事本编辑的XML文件时,这些差异可能导致计数子节点时的结果不一致。一个示例显示,对于包含空格和换行的XML,IE会报告4个子节点,而其他浏览器可能报告9个。