# React之domdiff策略
# 一:Tree Diff
TIP
- Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。
- 对树按层级递归比较,两棵树只会对同一层次的节点进行比较。当发现节点已经不存在时,则该节点及其子节点会被完全删除掉,不会用于进一步的比较;
- 当出现了
DOM节点跨层级的移动操作,React不会移动,而是直接删除节点并重新创建
这是一种影响React性能的操作 ,因此官方建议不要进行DOM节点跨层级的操作;
# 二:Component Diff
TIP
- 如果是同一类型的组件,按照原策略继续比较虚拟
DOM树即可; - 如果不是,则将该组件判断为
dirty component,从而替换整个组件下的所有子节点;
# 三:Element Diff
当节点处于同一层级时,React 会根据元素的 key 属性来识别节点:
INSERT_MARKUP(插入):
- 当新的组件类型不在旧集合里,即全新的节点,需要对新节点执行插入操作;
MOVE_EXISTING(移动);
- 旧集合中有新组件类型,且
element是可更新的类型,这种情况下,就需要做移动操作,可以复用以前的DOM节点;
REMOVE_NODE(删除);
- 旧组件类型,在新集合里也有,但对应的
element不同则不能直接复用和更新,需要执行删除操作,或者旧组件不在新集合里的,也需要执行删除操作。
React发现这类操作烦琐冗余,因为这些都是相同的节点,但由于位置发生变化,导致需要进行繁杂低效的删除、创建操作,其实只要对这些节点进行位置移动即可;
针对这一现象,React提出了优化策略:允许开发者对同一层级的同组子节点,添加唯一key进行区分,这样在性能上就发生了翻天覆地的提升;
新旧集合所包含的节点如图 3-22 所示,进行 diff 差异化对比后,通过 key 发现新旧集合中的节点都是相同的节点,因此无需进行节点删除和创建,只需要将旧集合中节点的位置进行移动,更新为新集合中节点的位置,此时 React 给出的 diff 结果为:B、D 不做任何操作,A、C 进行移动操作即可。
