一直想学习 React 源码,终于今天看完了 ReactChildren 的源码,特来阐述下学到的知识。写这篇文章,是受到 剖析 React 源码:先热个身 的启发,希望这篇文章可以带来不一样的体验。
打开 ReactChildren.js
文件内部暴露出下面几个方法。
export {
forEachChildren as forEach,
mapChildren as map,
countChildren as count,
onlyChild as only,
toArray
};
- 判断
children
是否为null
,如果是,则return children
。 - 调用
getPooledTraverseContext
方法获取traverseContext
对象,此方法是维护一个对象池,每次都会先去对象池内取对象,如果对象池没有对象,则新建,否则取出最后一个对象,修改属性值再使用。 - 调用
traverseAllChildrenImpl
,如果是可渲染节点,则调用forEachSingleChild
方法。如果是数组或类数组,则再次调用traverseAllChildrenImpl
。
-
判断
children
是否为null
,如果是,则return children
,如果不是,则调用mapIntoWithKeyPrefixInternal
。 -
同
forEachChildren
第二步。 -
同
forEachChildren
第三步。但是map
方法对于可渲染节点调用的方法是mapSingleChildIntoContext
。这个函数会判断函数返回值是否为数组,如果是,则再次循环调用mapIntoWithKeyPrefixInternal
。这样也就意味着,当你写如下代码时候,最终结果仍是一维数组。ReactChildren.mapChildren(this.props.children, (child)=>{ return [child, child] })