React.createElement

在写React,我们经常创建一个jsx文件,在里面编写代码就可以了,我们看看JSX转换后的代码


image.png

实际调用的就是React.createElement,直接看里面做了什么


第一部分

export function createElement(type, config, children) {
  let propName;

  // Reserved names are extracted
  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    if (hasValidRef(config)) {
      ref = config.ref;
      if (__DEV__) {
        warnIfStringRefCannotBeAutoConverted(config);
      }
    }
    if (hasValidKey(config)) {
      key = '' + config.key;
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source;
    // Remaining properties are added to a new props object
    for (propName in config) {
      if (
        hasOwnProperty.call(config, propName) &&
        !RESERVED_PROPS.hasOwnProperty(propName)
      ) {
        props[propName] = config[propName];
      }
    }
  }
    
}

1.定义了一些props,key、ref、self、source变量,判断config(就是元素上的属性配置对象)有的话进行处理
a.赋值我们常用的ref和key,还有些self和source
b.遍历config对象,把除了key ref __self __source 都放入到定义的props对象里;这也是我们经常为什么开发中props不能传递的原因,key ref关键字会单独处理不会到props里

下面代码

const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    if (__DEV__) {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }
    props.children = childArray;
  }

  // Resolve default props
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );

1、获取createElement传递的参数arguments,前面两个type, config去掉,获取后面多个children参数

2、如果只有一个children 给props设置children,有多个children,遍历放入到childArray中,最后给props设置children

3、找到组件里的defaultProps属性,开发中我们经常定义一个静态的defaultProps来给默认的props初始值,这里判断后,找到里面定义的给props传递的初始化值

4、最后返回一个ReactElement函数

const ReactElement = function(type, key, ref, self, source, owner, props) {
    const element = {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE,

    // Built-in properties that belong on the element
    type: type,
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this element.
    _owner: owner,
  };
  
  return element;
}

1.创建一个element对象,定义$$typeof为react的element-type类型,这个定义在后续的fiber.合成事件、更新中都会用到这个值判断

2.返回这个对象。

综上所述,其实createElement就是创建了props对象并赋值且单独处理的ref、key等,最后返回一个type为REACT_ELEMENT_TYP的element对象


你可能感兴趣的:(React.createElement)