React18 源码解析之 placeChild 的执行

React18 源码解析之 placeChild 的执行

蚊子前端博客
发布于 2022-09-19 09:21
在 React fiber 对比的过程中,有用到 placeChild() 函数,这个函数是做什么的呢?

我们解析的源码是 React18.1.0 版本,请注意版本号。React 源码学习的 GitHub 仓库地址:https://github.com/wenzi0github/react

在 React fiber 对比的过程中,有用到 placeChild() 函数,这个函数是做什么的呢?

此方法是一种顺序优化手段,lastPlacedIndex 一直在更新,初始为 0,表示访问过的节点在旧集合中最右的位置(即最大的位置)。如果新集合中当前访问的节点比 lastPlacedIndex 大,说明当前访问节点在旧集合中就比上一个节点位置靠后,则该节点不会影响其他节点的位置,因此不用添加到差异队列中,即不执行移动操作。只有当访问的节点比 lastPlacedIndex 小时,才需要进行移动操作。

lastPlaceIndex 表示当前复用到的旧 fiber 的最大索引,初始时为 0。比如第一个新 fiber 节点复用的是最后一个旧 fiber 节点,那 lastPlaceIndex 就是最后那个旧 fiber 节点的索引值。

1. 样例 1

COPYJAVASCRIPT

return !flag ? [
  • 0
  • ,
  • 1
  • ,
  • 2
  • ] : [
  • 0
  • ,
  • 2
  • ,
  • 2
  • ];

    -蚊子的前端博客

    过程描述:

    1. lastPlaceIndex 初始时为 0;

    2. 新节点 key1,Map 集合中存在 key1 则取出复用,key1 老节点的 oldIndex 为 1,不满足 oldIndex

    3. 新节点 key2,Map 集合中存在 key2 则取出复用,key2 老节点的 oldIndex 为 2,不满足 oldIndex

    4. 新节点 key0,Map 集合中存在 key0 则取出复用,key0 老节点的 oldIndex 为 0,满足 oldIndex

    2. 样例 2

    COPYJAVASCRIPT

    return !flag ? [
  • 0
  • ,
  • 1
  • ,
  • 2
  • ,
  • 2
  • ] : [
  • 1
  • ,
  • 0
  • ,
  • 3
  • ,
  • 2
  • ];

    -蚊子的前端博客

    过程描述:

    1. lastPlaceIndex 初始时为 0;

    2. 新节点 key1,Map 集合中存在 key1 则取出复用,key1 老节点的 oldIndex 为 1,不满足 oldIndex

    3. 新节点 key0,Map 集合中存在 key0 则取出复用,key0 老节点的 oldIndex 为 0,满足 oldIndex

    4. 新节点 key3,Map 集合中存在 key3 则取出复用,key3 老节点的 oldIndex 为 3,不满足 oldIndex

    5. 新节点 key2,Map 集合中存在 key2 则取出复用,key2 老节点的 oldIndex 为 2,满足 oldIndex

    3. 样例 3:

    COPYJAVASCRIPT

    return !flag ? [
  • 0
  • ,
  • 1
  • ,
  • 2
  • ,
  • 2
  • ] : [
  • 1
  • ,
  • 5
  • ,
  • 3
  • ,
  • 0
  • ];

    -蚊子的前端博客

    过程描述:

    1. lastPlaceIndex 初始时为 0;

    2. 新节点 key1,Map 集合中存在 key1 则取出复用,key1 老节点的 oldIndex 为 1,不满足 oldIndex

    3. 新节点 key5,Map 集合中不存在 key5 新建节点,不满足 current !== null,则将 key5 标记为插入,返回 lastPlacedIndex。

    4. 新节点 key3,Map 集合中存在 key3 则取出复用,key3 老节点的 oldIndex 为 3,不满足 oldIndex

    5. 新节点 key0,Map 集合中存在 key0 则取出复用,key0 老节点的 oldIndex 为 0,满足 oldIndex

    6. 剩余节点 key2 通过 existingChildren 遍历删除,被复用过的节点因为从 map 集合中已经移除了,所以这里的删除只是为被复用的。

    4. 样例 4(性能差的一种情况)

    COPYJAVASCRIPT

    return !flag ? [
  • 0
  • ,
  • 1
  • ,
  • 2
  • ] : [
  • 2
  • ,
  • 0
  • ,
  • 1
  • ];

    -蚊子的前端博客

    过程同上,但是这种操作会使得顺序优化算法失去效果,除了最后一个节点没有 effect,其他节点都会被执行插入操作,所以尽量避免将最后一个节点更新到第一个节点的位置操作。

    参考文章:

    标签:

    阅读(340)

    公众号:

    qrcode

    微信公众号:前端小茶馆

    版权声明:
    作者:Joker 链接:https://hooper.eu.org/archives/47489
    文章版权归作者所有,转载请注明出处。
    THE END
    分享
    二维码
    打赏
    < <上一篇
    下一篇>>