一、react 中的虚拟 DOM
- 第一种方案:
- 第一步,
state
数据 - 第二步,
JSX
模版 - 第三步,数据 + 模版的结合,生成真实的
DOM
,来显示 - 第四步,
state
发生改变 - 第五步,数据 + 模版的结合,生成真实的
DOM
,替换原始的DOM
缺陷: 第一次生成了一个完整的 DOM
片段,第二次生成了一个完整的 DOM
片段,用第二次的DOM
替换第一次的 DOM
,非常耗性能
- 第二种方案:
- 第一步,
state
数据 - 第二步,
JSX
模版 - 第三步,数据 + 模版的结合,生成真实的
DOM
,来显示 - 第四步,
state
发生改变 - 第五步,数据 + 模版的结合,生成真实的
DOM
,并不直接替换原始的DOM
- 第六步,新的
DOM(DoucumentFragment)
和原始的DOM
做对比,找差异 - 第七步,找出
span
发生了变化 - 第八步,只用新的
DOM
中的span
元素,替换掉老的DOM
中的span
元素
缺陷:性能的提升并不明显
- 第三种方案:
- 第一步,
state
数据 - 第二步,
JSX
模版 - 第三步,数据 + 模版的结合,生成虚拟 DOM,虚拟 DOM 就是一个JS对象,用它来描述真实 DOM,耗损了性能
['div', {id: 'abc'}, ['span', {}, 'hello word'] ]
- 第四步,用虚拟
DOM
的结构生成真实的DOM
,来显示<div id="abc"><span>hello word</span></div>
- 第五步,
state
发生变化 - 第六步,数据 + 模版生成新的虚拟 DOM,极大的提升了性能
['div', {id: 'abc'}, ['span', {}, 'hello react'] ]
- 第七步,比较原始虚拟
DOM
和新的虚拟DOM
的区别,找打区别是span
中的内容,极大的提升了性能 - 第八步,直接操作
DOM
, 改变span
中的内容
优点:性能的提升很明显,它使得跨端应用得以实现,React Native
-
一个虚拟
DOM
元素是一个一般的JS
对象,准确的说是一个对象树,倒立的,虚拟DOM
保存了真实DOM
的层次关系和一些基本属性,与真实DOM
一一对应,如果只是更新虚拟DOM
,页面是不会重绘的。 -
对真实
DOM
进行比较耗性能,而对JS
对象进行耗性能较小。虚拟DOM
对于react
的好处是减少了对真实DOM
的创建和真实DOM
的对比,反而创建的都是JS
对象,对比的也是JS
对象,react
的底层性能也得到了很大的提升。
二、DOM diff算法
-
setState
底层可以将多次setState
结合成一次setState
,减少虚拟DOM
的比对次数,如下图所示:
-
react
的虚拟DOM
比对是同层比对,逐层比对,如果一层不满足匹配的要求时,下面的就不会再 比对了,直接废弃掉,用新的替换掉老的,提升性能,如下图所示:
-
react
中引入key
值,提高比较虚拟DOM
的性能,key
值要稳定,能不用index
就不用index
,因为index
的key
值是不稳定的,如下图所示:
-
Virtual DOM
算法的基本步骤:
用JS
对象树表示DOM
树的结构;然后用这个树构建一个真正的DOM
树插到文档当中。当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异,把差异应用到真实DOM
树上,视图就更新了。同层比对和key
值都是diff
算法的一部分。 -
Virtual DOM
本质上就是在JS
和DOM
之间做了一个缓存。可以类比CPU
和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存:既然DOM
这么慢,我们就在它们JS
和DOM
之间加个缓存。CPU
(JS
)只操作内存(Virtual DOM
),最后的时候再把变更写入硬盘(DOM
)。