# React之domdiff策略
# 一:Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。
TIP
1、
React
对树的算法进行了优化,对树进行分层比较,两棵树只会对同一层次的节点进行比较:只会对相同层级的DOM
节点进行比较,即同一个父节点下的所有子节点。当发现节点已经不存在时,则该节点及其子节点会被完全删除掉,不会用于进一步的比较;这样只需要对树进行一次遍历,便能完成整个DOM
树的比较2、当出现了
DOM
节点跨层级的移动操作,domdiff会怎么做?当出现节点跨层级移动时,并不会出现我们所想象的移动操作,而是以A为根节点的整个树被重新创建。这是一种影响
React
性能的操作 ,因此官方建议不要进行DOM
节点跨层级的操作;
# 二:component diff
TIP
- 1、如果是同一类型的组件,按照原策略继续比较虚拟
DOM
树即可; - 2、如果不是,则将该组件判断为
dirty component
,从而替换整个组件下的所有子节点; - 3、对于同一类型的组件,有可能其虚拟
DOM
没有发生任何变化,如果能够确切知道这点,那么就可以节省大量的diff
运算时间,因此,React
允许用户通过shouldComponentUpdate()
生命周期函数来判断组件是否需要进行diff
算法分析;- 如:通过三元运算符判断展示对应组件的时候,当
D
组件变为G
组件时,即使这两个组件结构相似,一旦react
判断D
和G
是不同类型的组件,就不会比较二者的结构,而是直接删除组件D
,重新创建组件G
及其子节点。
- 如:通过三元运算符判断展示对应组件的时候,当
# 三:element diff
当节点处于同一层级时,diff提供了三种节点操作,分别为
- 1、
INSERT_MARKUP
(插入):- 当新的组件类型不在旧集合里,即全新的节点,需要对新节点执行插入操作;
- 2、
MOVE_EXISTING
(移动);- 旧集合中有新组件类型,且
element
是可更新的类型,这种情况下,就需要做移动操作,可以复用以前的DOM
节点;
- 旧集合中有新组件类型,且
- 3、
REMOVE_NODE
(删除);- 旧组件类型,在新集合里也有,但对应的
element
不同则不能直接复用和更新,需要执行删除操作,或者旧组件不在新集合里的,也需要执行删除操作。
- 旧组件类型,在新集合里也有,但对应的
React
发现这类操作烦琐冗余,因为这些都是相同的节点,但由于位置发生变化,导致需要进行繁杂低效的删除、创建操作,其实只要对这些节点进行位置移动即可;
针对这一现象,React
提出了优化策略:允许开发者对同一层级的同组子节点,添加唯一key
进行区分,这样在性能上就发生了翻天覆地的提升;
新旧集合所包含的节点如图 3-22 所示,进行 diff
差异化对比后,通过 key
发现新旧集合中的节点都是相同的节点,因此无需进行节点删除和创建,只需要将旧集合中节点的位置进行移动,更新为新集合中节点的位置,此时 React
给出的 diff
结果为:B、D
不做任何操作,A、C
进行移动操作即可。