react dom diff

25 阅读1分钟

分为两种:单节点和多节点。这个单节点和多节点是指新生成的 JSX 对象里面的 newChild 是不是数组。

都是比较 newChild 和 currentFiber 生成 workInProgressFiber 的过程。

单节点 diff

以 REACT_ELEMENT_TYPE 为例。

  1. 如果 key 不同,则将此 fiber 标记为删除;
  2. 如果 key 相同,再比较 type 是否一致
  3. 如果 type 一致,则复用此 fiber,然后将 fiber.sibling 之后的所有 fiber 删除
  4. 如果 type 不一致,则将所有的 fiber 均删除

多点节 diff

更新节点、删除/插入节点、交换节点位置。由于更新的发生的更频繁,所以分为两步走,先处理更新,再处理其他情况。

  1. 处理更新节点

    1. 比较 newChildren[i++] 是不是可以复用 currentFiber.sibling
    2. 如果 key 不同,跳出循环
    3. 如果 key 相同,比较 type
    4. 如果 type 相同,复用 currentFiber
    5. 如果 type 不同,将 currentFiber 标记为删除,将 newChild 创建 fiber 标记为新增
    6. 比较结束后跳出循环
  2. 处理剩下不属于更新的节点

    1. currentFiber 遍历完成,将 newChild 创建 fiber 标记新增
    2. newChild 遍历完成,currentFiber 标记删除
    3. 均未遍历完成
    4. 将 currentFiber 做成一个 {key: fiber} 的 map
    5. 遍历 newChild 然后判断是不是可以重用以及 placementIndex,重用后从 map 里面删除
    6. 最后将 map 里面的所有元素都标记为删除