# 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 进行移动操作即可。
