react源码流程图—— ReactChildren

本文阅读react16.8.6版本ReactChildren.js文件。下面从mapChildren函数入手,给出React.Children.map的流程图。

请参考React源码阅读本文。

 

 

 mapChildren遍历每个子节点调用函数并摊平子节点。

摊平子节点,即,把['a', ['b'], [['c'], 'd']]摊平成['a', 'b', 'c', 'd']

如果我们想自己实现摊平功能,我们会怎么写这个函数:

很简单的功能,为什么React写得那么复杂?我们来看下traverseAllChildren到底做了些什么。

根据我们画出的流程图,我们可以知道,React流程图红框中的内容对应我们蓝框中的代码。

(代码写多了,疏于言表?,用框框箭头代码示意,你们可以意会吧?‍♂️)

这么看,貌似挺简单的。但是,我们要知道,React是要把执行用户输入的func(即React.Children.map(this.props.children, c=>[c,[c]])中的c=>[c,[c]]函数)后所得到的mappedChild进行平铺。所以我们修改myTraverseAllChildren函数。如下。

现在的myTraverseAllChildren和我们先前写的有啥区别?

区别在于:先前写的,是将形参arr平铺到result中;而现在写的,是将形参arr的每个元素经过func处理后得到的新值(该值可能是任何类型)平铺到result中。

现在我们的myMapSingleEle函数对应React的mapSingleChildIntoContext。我们将两者进行对比,找出mapSingleChildIntoContext中逻辑和我们不一样的地方,并思考为什么。

我们发现,我们的myMapSingleEle函数和React的mapSingleChildIntoContext不同处在于:①当判断mappedSth为数组的时候,我们调用myTraverseAllChildren,而React调用一开始的mapIntoWithKeyPrefixInternal。②当mappedSth不为空时,mapSingleChildIntoContext还需判断是否是有效元素,如果是的话,就执行cloneAndReplaceKey。

第二点我们知道React是想要克隆并替换Key,使相同child副本的key均不同。

如:console.log(React.Children.map(this.props.children, c => [[c,c],c]))

控制台输出:

那么,为什么React调用之前的mapIntoWithKeyPrefixInternal,而不是traverseAllChildrenImpl?cloneAndReplaceKey函数看名称的意思是克隆并替换Key,那为什么要克隆并替换Key呢?

先看第一个问题。我们看mapIntoWithKeyPrefixInternal函数和traverseAllChildrenImpl函数有什么不同。

回头看我们流程图,我们发现,mapIntoWithKeyPrefixInternal包含traverseAllChildren,包含traverseAllChildrenImpl。主要就是比traverseAllChildrenImpl多了从对象重用池获取traverseContext和释放traverseContext的逻辑。我们思考,这个逻辑是干嘛的?可不可以不要这个逻辑?

为了看懂这个逻辑,我们又画了一个图。

如上图所给出的示例,如果没有这个逻辑,代码将开辟5个这样子的内存空间,但有了对象重用池,我们只开辟了3个空间。既节省了新开辟空间所需的时间,又节省了内存空间占用。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值