ReactChildren
React源码
通用方法
traverseContext
traverseContext 中保存着遍历过程中用户可能接触的数据。result 为执行结果,keyPrefix 保存了与遍历路径相关的信息,func 为用户传入的回调函数,context 为执行上下文
这个对象通常保存在 traverseContextPool 中,通过 getPooledTraverseContext 取出并初始化,通过 releaseTraverseContext 方法格式化并放回
traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext)
这个函数是 React.Children 中所有方法中使用到的遍历方法,这部分逻辑会被递归调用
children 参数可以是 ReactElement、字符串、数字以及包含这些类型的可迭代对象。当 children 为可迭代对象时会对其中的元素分别进行递归调用。
callback 为 React 内置的一些回调函数,这个值因方法而异。最后会调用 callback(traverseContext, children, nameSoFar)
nameSoFar 是由路径上元素的 key 和数组元素的 index 组成的字符串,形如 ".$key
/.index
/.index
/.$key
"
这个函数的返回值为遍历的元素总数,包括数组中的元素而不包括数组本身。
traverseAllChildren(children, callback, traverseContext)
对 nameSoFar 进行初始化,然后调用 traverseAllChildrenImpl。
forEach(children, func, context)
forEach(children, forEachFunc, forEachContext)
- 用 func 和 context 初始化一个 traverseContext
- forEachSingle 作为回调函数和 traverseContext 一同传入 traverseAllChildren。
forEachSingleChild(bookKeeping, child, name)
使用的 func 和 context 执行回调函数。
map(children, func, context)
mapChildren(children, func, context)
建立一个数组作为 result 传入 mapIntoWithKeyPrefixInternal
mapIntoWithKeyPrefixInternal(children, array, prefix, func, context)
这个函数会被递归调用。
- 初始化 prefix,被递归调用时在 prefix 后插入'/'作为分隔符。
- 用 array, prefix, func, context 初始化一个 traverseContext
- mapSingleChildIntoContext 作为回调函数和 traverseContext 一同传入 traverseAllChildren
mapSingleChildIntoContext(bookKeeping, child, childKey)
- 使用的 func 和 context 执行回调函数并取得返回值 mappedChild。
- 根据 mappedChild 的类型不同而采取不同的操作
- mappedChild 为数组时对其中每个元素递归调用 mapIntoWithKeyPrefixInternal,以一个直接将收到的元素推入 result 的函数作为 callback
- mappedChild 为 ReactElement 时复制这个元素并且对 key 作出一些修改,这种情况下原元素的 key 值不会被 escape,结果形如 '
key
/.$key
'
- mappedChild 为其他值时正常推入 traverseContext.result 中
count(children)
countChildren(children, context)
traverseAllChildren 本身就会返回遍历元素的数量,因此传入一个空函数作为 callback 即可
toArray(children)
toArray(children)
将一个直接返回收到的元素的函数作为 callback 传入 mapIntoWithKeyPrefixInternal
onlyChild(children)
onlyChild(children)
props.children 中只有一个 child 时,props.chilren 会是 reactElement 而不是数组,因此直接检测其类型即可