React.createElement

878 阅读1分钟

在写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);
};