# React之domdiff策略

# 一:Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。

TIP

  • 1、React对树的算法进行了优化,对树进行分层比较,两棵树只会对同一层次的节点进行比较:只会对相同层级的DOM节点进行比较,即同一个父节点下的所有子节点。当发现节点已经不存在时,则该节点及其子节点会被完全删除掉,不会用于进一步的比较;这样只需要对树进行一次遍历,便能完成整个DOM树的比较

  • 2、当出现了DOM节点跨层级的移动操作,domdiff会怎么做? react-4-1

    当出现节点跨层级移动时,并不会出现我们所想象的移动操作,而是以A为根节点的整个树被重新创建。这是一种影响React性能的操作 ,因此官方建议不要进行DOM节点跨层级的操作;

# 二:component diff

TIP

  • 1、如果是同一类型的组件,按照原策略继续比较虚拟DOM树即可;
  • 2、如果不是,则将该组件判断为dirty component,从而替换整个组件下的所有子节点;
  • 3、对于同一类型的组件,有可能其虚拟DOM没有发生任何变化,如果能够确切知道这点,那么就可以节省大量的diff运算时间,因此,React允许用户通过shouldComponentUpdate()生命周期函数来判断组件是否需要进行diff算法分析;
    • 如:通过三元运算符判断展示对应组件的时候,当D组件变为G组件时,即使这两个组件结构相似,一旦react判断DG是不同类型的组件,就不会比较二者的结构,而是直接删除组件D,重新创建组件G及其子节点。
    • react-4-2

# 三:element diff

当节点处于同一层级时,diff提供了三种节点操作,分别为

  • 1、INSERT_MARKUP(插入):
    • 当新的组件类型不在旧集合里,即全新的节点,需要对新节点执行插入操作;
  • 2、MOVE_EXISTING (移动);
    • 旧集合中有新组件类型,且element是可更新的类型,这种情况下,就需要做移动操作,可以复用以前的DOM节点;
  • 3、REMOVE_NODE(删除);
    • 旧组件类型,在新集合里也有,但对应的 element 不同则不能直接复用和更新,需要执行删除操作,或者旧组件不在新集合里的,也需要执行删除操作。
react-4-3

React发现这类操作烦琐冗余,因为这些都是相同的节点,但由于位置发生变化,导致需要进行繁杂低效的删除、创建操作,其实只要对这些节点进行位置移动即可;

针对这一现象,React提出了优化策略:允许开发者对同一层级的同组子节点,添加唯一key进行区分,这样在性能上就发生了翻天覆地的提升;

新旧集合所包含的节点如图 3-22 所示,进行 diff 差异化对比后,通过 key 发现新旧集合中的节点都是相同的节点,因此无需进行节点删除和创建,只需要将旧集合中节点的位置进行移动,更新为新集合中节点的位置,此时 React 给出的 diff 结果为:B、D 不做任何操作,A、C 进行移动操作即可。

react-4-4
上次更新: 5/19/2020, 7:08:23 PM