traverseAllChildren模块供ReactChildren模块使用,用于遍历ReactNode形式的集合props.children或其他props属性。
traverseAllChildren(children,function(traverseContext,child,name){}, traverseContext){}函数的第三个参数将作为回调函数的首参。ReactChildren模块调用traverseAllChildren时,traverseContext存储遍历的执行函数,用于执行traverseContext.func方法;flattenChildren模块调用时,traverseContext作为引用传递输出的最终结果result,用于将子元素扁平化。
'use strict'; var _prodInvariant = require('./reactProdInvariant');// 生产环境React形式带url报错 // 容器组件,用户自定义组件的ReactCompositeComponent实例化、render过程中,给ReactCurrentOwner.owner赋值 var ReactCurrentOwner = require('./ReactCurrentOwner'); // 判断是否ReactElement var REACT_ELEMENT_TYPE = require('./ReactElementSymbol'); var getIteratorFn = require('./getIteratorFn'); // invariant(condition,format,a,b,c,d,e,f) condition为否值,替换format中的"%s",并throw error报错 var invariant = require('fbjs/lib/invariant'); // 用于React元素的key属性转化 var KeyEscapeUtils = require('./KeyEscapeUtils'); // warning(condition,format) condition为否值,替换format中的"%s",并console.error警告 var warning = require('fbjs/lib/warning'); var SEPARATOR = '.'; var SUBSEPARATOR = ':'; var didWarnAboutMaps = false; function getComponentKey(component, index) { if (component && typeof component === 'object' && component.key != null) { // 正则替换"="或":"为"=0"、"=2" return KeyEscapeUtils.escape(component.key); } return index.toString(36); } // 当props.children为单节点形式时,对该节点执行callback回调,间接执行traverseContext.func函数 // 当props.children为嵌套节点形式时,递归调用traverseAllChildrenImpl遍历子孙节点,通过callback回调执行traverseContext.func函数 function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) { var type = typeof children; if (type === 'undefined' || type === 'boolean') { children = null; } // 作为单一节点ReactNode处理,通过回调callback间接执行traverseContext.func函数或塞入traverseContext中 if (children === null || type === 'string' || type === 'number' || type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE) { callback(traverseContext, children, nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar); return 1; } var child; var nextName; var subtreeCount = 0; // 统计props.children中含有的节点个数 var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR; // props.children成数组形式,遍历子孙节点执行callback回调 // 通过回调callback间接执行traverseContext.func函数或塞入traverseContext中 if (Array.isArray(children)) { for (var i = 0; i < children.length; i++) { child = children[i]; nextName = nextNamePrefix + getComponentKey(child, i); subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); } // props.children为迭代器,遍历子孙节点执行callback回调 // 通过回调callback间接执行traverseContext.func函数或塞入traverseContext中 } else { var iteratorFn = getIteratorFn(children); if (iteratorFn) { var iterator = iteratorFn.call(children); var step; if (iteratorFn !== children.entries) {// 有关entries属性??? var ii = 0; while (!(step = iterator.next()).done) { child = step.value; nextName = nextNamePrefix + getComponentKey(child, ii++); subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); } } else { if (process.env.NODE_ENV !== 'production') { var mapsAsChildrenAddendum = ''; if (ReactCurrentOwner.current) { var mapsAsChildrenOwnerName = ReactCurrentOwner.current.getName(); if (mapsAsChildrenOwnerName) { mapsAsChildrenAddendum = ' Check the render method of `' + mapsAsChildrenOwnerName + '`.'; } } process.env.NODE_ENV !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.%s', mapsAsChildrenAddendum) : void 0; didWarnAboutMaps = true; } while (!(step = iterator.next()).done) { var entry = step.value; if (entry) { child = entry[1]; nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0); subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext); } } } // 不能接受的对象格式数据,输出相应的错误 } else if (type === 'object') { var addendum = ''; if (process.env.NODE_ENV !== 'production') { addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.'; if (children._isReactElement) { addendum = ' It looks like you\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.'; } if (ReactCurrentOwner.current) { var name = ReactCurrentOwner.current.getName(); if (name) { addendum += ' Check the render method of `' + name + '`.'; } } } var childrenString = String(children); !false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0; } } return subtreeCount; } // 用于遍历props.children或其他props属性(传递ReactNode),执行callback回调函数 // callback执行过程调用traverseContext.func对child进行处理,或者将child塞入traverseContext中 function traverseAllChildren(children, callback, traverseContext) { if (children == null) { return 0; } return traverseAllChildrenImpl(children, '', callback, traverseContext); } // traverseAllChildren(children,function(traverseContext,child,name){}, traverseContext){}函数的第三个参数将作为回调函数的首参 // react包下ReactChildren模块中,traverseContext存储遍历的执行函数,用于执行traverseContext.func方法 // react包下flattenChildren模块中,traverseContext作为引用传递输出的最终结果result,用于将子元素扁平化 // react包下ReactChildReconciler模块中,traverseContext获取props.children相关react组件实例的集合 module.exports = traverseAllChildren;