React Children
文章目录
ReactChildren
提供了许多处理
props.children
的方法。本文将源码由上往下解析。
escape
function escape(key: string): string {
const escapeRegex = /[=:]/g;
const escaperLookup = {
'=': '=0',
':': '=2',
};
const escapedString = key.replace(escapeRegex, function(match) {
return escaperLookup[match];
});
return '$' + escapedString;
}
把key里面的:
替换成=0
,:
替换成=2
,这样key作为reactId更安全。
escapeUserProvidedKey
const userProvidedKeyEscapeRegex = /\/+/g;
function escapeUserProvidedKey(text: string): string {
return text.replace(userProvidedKeyEscapeRegex, '$&/');
}
把用户提供的所有/
(单个或多个)后面都再添加一个/
getElementKey
function getElementKey(element: any, index: number): string {
// 类型验证,并且元素的key不为空
if (typeof element === 'object' && element !== null && element.key != null) {
// 返回显示键,使用之前的escape方法保证安全性
return escape('' + element.key);
}
// 索引决定的隐式键
return index.toString(36);
}
生成一个可辨识元素的key。
mapIntoArray
function mapIntoArray(
children: ?ReactNodeList,
array: Array<React$Node>,
escapedPrefix: string,
nameSoFar: string,
callback: (?React$Node) => ?ReactNodeList,
): number {
const type = typeof children;
if (type === 'undefined' || type === 'boolean') {
如果children的类型是void或者布尔值,则认定无效,
children = null;
}
let invokeCallback = false;
if (children === null) {
// 如果children为空,触发回调函数
invokeCallback = true;
} else {
switch (type) {
case 'string':
case 'number':
// children 的类型为string和number同样触发回调函数
invokeCallback = true;
break;
case 'object':
switch ((children: any).$$typeof) {
// 如果children是一个ReactElement或者Portal,同样触发回调函数
case REACT_ELEMENT_TYPE:
case REACT_PORTAL_TYPE:
invokeCallback = true;
}
}
}
if (invokeCallback) {
const child = children;
let mappedChild = callback(child);
// 即使child只有一个,也将它作为数组对待
// 这样children数量增加也不会变
// 生成一个