在了解虚拟 DOM 之前,我们先看一下浏览器的渲染流程
- 解析获取到的 HTML 文档生成 DOM
- 解析 CSS 构成层叠样式表结构 CSSOM
- 将两者进行结合生成渲染树
- 浏览器根据渲染树上的节点信息确定其坐标值
- 调用每个节点的 paint 方法,将节点绘制到屏幕上
当我们使用原生 js 或者 jquery 操作 DOM 时,每对 DOM 进行一次操作,浏览器就会从头到尾执行一遍流程,当操作十分频繁时,对于浏览器的性能消耗便会变得非常严重。虚拟 DOM 就是为了解决浏览器性能问题而被设计出来的
什么是虚拟 DOM
相较于 DOM 对象,原生的 JavaScript 对象处理起来速度更快,也更简单。我们也可以用 JavaScript 对象表示出 DOM 树上的结构、属性信息,比如
COPY
1 | var element = { |
对应的 HTML 代码为
COPY
1 | <ul id="list"> |
既然 Javascript 对象属性可以用来描述 DOM 节点,那我们是不是可以通过一些操作将 Javascript 对象映射到真实 DOM 上
此时,我们边可以将虚拟 DOM 简单理解为一个 JS 对象,这个对象至少包含有标签名( tag)、属性(attrs)和子元素对象( children)三个属性。
虚拟 DOM 作用是什么
虚拟 DOM 的最终目的是将虚拟节点渲染到视图上,但如果直接覆盖的话,那虚拟 DOM 的存在也并没有什么意义了。为了避免不必要的 DOM 操作,虚拟 DOM 在将虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧节点进行对比,将真正需要更新内容的节点进行映射,避免操作其他无关的 DOM
总结一下,虚拟 DOM 主要做了两件事
- 通过 Javascript 对象构建虚拟节点
- 将本次的虚拟节点与上次的进行差异对比,再进行视图更新
虚拟 Dom 的优势
「Virtual Dom 的优势」其实这道题目面试官更想听到的答案不是上来就说「直接操作/频繁操作 DOM 的性能差」,如果 DOM 操作的性能如此不堪,那么 jQuery 也不至于活到今天。所以面试官更想听到 VDOM 想解决的问题以及为什么频繁的 DOM 操作会性能差。
首先我们需要知道:
- DOM 引擎、JS 引擎 相互独立,但又工作在同一线程(主线程)
- JS 代码调用 DOM API 必须 挂起 JS 引擎、转换传入参数数据、激活 DOM 引擎,DOM 重绘后再转换可能有的返回值,最后激活 JS 引擎并继续执行若有频繁的 DOM API 调用,且浏览器厂商不做“批量处理”优化,
- 引擎间切换的单位代价将迅速积累若其中有强制重绘的 DOM API 调用,重新计算布局、重新绘制图像会引起更大的性能消耗。
其次是 VDOM 和真实 DOM 的区别和优化:
- 虚拟 DOM 不会立马进行排版与重绘操作
- 虚拟 DOM 进行频繁修改,然后一次性比较并修改真实 DOM 中需要改的部分,最后在真实 DOM 中进行排版与重绘,减少过多 DOM 节点排版与重绘损耗
- 虚拟 DOM 有效降低大面积真实 DOM 的重绘与排版,因为最终与真实 DOM 比较差异,可以只渲染局部