export function createElement(type, config, children) {
//propName 变量用于储存后面需要用到的元素属性
let propName;
// props 变量用于储存元素属性的键值对集合
const props = {};
//key、ref、self、source均为react元素的属性
let key = null;
let ref = null;
let self = null;
let source = null;
//config对象中存储的元素的属性
if (config != null) {
//进来之后的第一件事: 依次对ref、key、self和source属性赋值
if (hasValidRef(config)) {
ref = config.ref;
if (__DEV__) {
warnIfStringRefCannotBeAutoConverted(config);
}
}
//此处将key值字符串化
if (hasValidKey(config)) {
//开发环境下的配置
if (__DEV__) {
checkKeyStringCoercion(config.key);
}
key = '' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
// 把config里面的属性一个一个挪到之前声明的props对象里面
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
}
//childrenLength指的是当前元素的子元素的个数,减去2是type和config两个参数占用的长度
const childrenLength = arguments.length - 2;
//如果除去type和config,就是剩一个参数,一般意味着文本节点出现了
if (childrenLength === 1) {
//直接把这个参数的值赋给props.children
props.children = children;
//处理嵌套多个子元素的情况
} else if (childrenLength > 1) {
//声明一个子元素数组
const childArray = Array(childrenLength);
//把子元素从arguments除去type和config推进childArray数组里
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
if (__DEV__) {
if (Object.freeze) {
Object.freeze(childArray);
}
}
//最后把数组赋值给props.children
props.children = childArray;
}
// 处理defaultProps
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
//开发环境下的配置
if (__DEV__) {
if (key || ref) {
const displayName =
typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (ref) {
defineRefPropWarningGetter(props, displayName);
}
}
}
//返回一个调用ReactElement执行方法,并传入刚才处理过的参数
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
React底层源码分析之------createElement
于 2022-04-13 11:08:35 首次发布