在写jsx语法时,通过babel会把他们转化为React.createElement(type,config,...children) type: 如果是组件类型,会传入组件对应的类或函数;如果是 dom 元素类型,传入 div 或者 span 之类的字符串, props: 一个对象,在 dom 类型中为标签属性,在组件类型中为 props children: 元素内容,可以有多个
// 定义一个RESERVED_PROPS对象
const RESERVED_PROPS = { key: true, ref: true, __self: true, __source: true };
ReactElement.createElement = function (type, config, children) {
var propName;
var props = {};
var key = null;
var ref = null;
var self = null;
var source = null;
// 从config中提取出内容,如ref key props
if (config != null) {
ref = config.ref === undefined ? null : config.ref;
key = config.key === undefined ? null : '' + config.key;
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
// 提取出config中的prop并排除ref,key,__self,__source,放入props变量中,所以props中无法获取到ref等等
for (propName in config) {
if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName];
}
}
}
// 处理children,挂到props的children属性下
// 入参的前两个为type和config,后面的就都是children参数了。故需要减2
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
// 只有一个参数时,直接挂到children属性下
props.children = children;
} else if (childrenLength > 1) {
// 不止一个时,新建一个数组,并把他们放进数组之中
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
}
// 取出组件类中的静态变量defaultProps,并给未在JSX中设置值的属性设置默认值
if (type && type.defaultProps) {
var defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
// 返回一个ReactElement对象
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
};