React 多节点 diff 如何移动?

38 阅读1分钟

接上回。

先看第一个 demo。

<!-- 更新前 --> 

<ul>
    <li key="jd">jingdong</li>
    <li key="tx">tengxun</li>
    <li key="hw">huawei</li>
    <li key="xm">xiaomi</li>
</ul>

<!-- 更新后 --> 

<ul>
    <li key="jd">jingdong</li>
    <li key="hw">huawei</li>
    <li key="xm">xiaomi</li>
    <li key="tx">tengxun</li>
</ul>

定义 lastPlacedIndex 表示上一次可复用节点的索引,oldIndex 表示更新前节点的索引(从 0 开始)。

如果 oldIndex 大于 lastPlacedIndex 则更新 lastPlacedIndexoldIndex;如果 oldIndex 小于 lastPlacedIndex 则移动

需要执行两轮遍历:

第一轮:

  1. 比较更新前后的第一个节点,key 都是 jd,没有没变,可以复用,lastPlacedIndex = 0
  2. 比较更新前后的第二个节点,旧的 keytx,新的 keyhw,结束第一次遍历(key 不同直接结束遍历)

第二轮:

  1. 从更新后的第二个节点 hw 开始,oldIndex 是 2,大于 lastPlacedIndex(大于 0),可以复用,更新 lastPlacedIndex 为 2
  2. 第三个节点 xmoldIndex 是 3,大于 lastPlacedIndex(大于 2),可以复用,更新 lastPlacedIndex 为 3
  3. 第四个节点 txoldIndex 是 1,小于 lastPlacedIndex(小于 3),向后移动。

结论:移动 tx,其他三个节点保持不变

注意:向后移动方向是从前向后

再看第二个 demo,加深理解。

<!-- 更新前 --> 

<ul>
    <li key="jd">jingdong</li>
    <li key="tx">tengxun</li>
    <li key="hw">huawei</li>
    <li key="xm">xiaomi</li>
</ul>

<!-- 更新后 --> 

<ul>
    <li key="xm">xiaomi</li>
    <li key="jd">jingdong</li>
    <li key="tx">tengxun</li>
    <li key="hw">huawei</li>
</ul>

同样需要执行两轮遍历:

第一轮:

  1. 比较更新前后的第一个节点,旧 key 的是 jd,新的 keyxm,结束第一次遍历

第二轮:

  1. 更新后的第一个节点 xmoldIndex 是 3,赋值 lastPlacedIndex 为 3
  2. 第二个节点 jdoldIndex 是 0,小于 lastPlacedIndex(小于 3),向后移动
  3. 第三个节点 txoldIndex 是 1,小于 lastPlacedIndex(小于 3),向后移动
  4. 第四个节点 hwoldIndex 是 2,小于 lastPlacedIndex(小于 3),向后移动

结论:xm 不变,其他三个节点向后移动