react源码系列之三、Diff算法

159 阅读1分钟

1 流程概览

  • 一个DOM节点最多会有四个节点与之关联,如下图: image.png

  • React在Diff算法的优化:

    • 只对同级元素进行Diff。如果一个DOM节点在前后两次更新中跨越了层级,则不再复用他;
    • 类型不同时会销毁它及其子节点再新建;(如下面的p和span都会销毁再新建)
<div>
  <p>p节点</p>
  <span>span节点</span>
</div>
//更新为 ↓
<div>
  <span>span节点</span>
  <p>p节点</p>
</div>
  • 设置key值可告诉react哪些可复用。(如下例子只会交换p和span的顺序)
<div>
  <p key="p">p节点</p>
  <span key="span">span节点</span>
</div>
//更新为 ↓
<div>
  <span key="span">span节点</span>
  <p key="p">p节点</p>
</div>
  • Diff的入口 在reconcileChildFibers(returnFiber,currentFirstChild,newChild)内会根据newChild(返回的jsx对象)的类型(object,array等)选择不同的处理函数。 image.png

2 单一节点的Diff

以Object类型为例,会进入reconcileSingleElement方法 image.png

3 多节点的diff

  • 当child存在多个同级节点时,如下面的div的子节点:
<div>
  <p>p节点</p>
  <span>span节点</span>
</div>
  • 前后变化有以下三种情况:
    • 节点更新(包括属性和类型)
    • 节点新增或减少
    • 节点位置变换
  • diff的思路
    • 因为更新的频率比新增或删除高,且要对比的newChildren和curretFiber一个是数组一个是链表,无法使用双指针遍历,所以react团队将整个diff算法分成了两轮遍历:
    • 处理更新的节点 --> 处理剩下的不属于更新的节点
  • 流程图
    • 较为复杂,正在学习...