React.createElement 源码思考

https://github.com/facebook/react/blob/master/packages/react/src/ReactElement.js

// ** ReactElement 是 createElement的核心方法。作用是很简单,就是返回一个信息的承载容器,表明渲染节点的信息。
const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // $$typeof 用来标识我们的Element的什么类型的。比如我们在写jsx代码的时候,所有的节点都是通过createElement创建的,那么它的$$typeof就永远是REACT_ELEMENT_TYPE,也就是说大部分情况下 这个值都是固定的。(用于确定是否属于ReactElement)
    // 源码:const REACT_ELEMENT_TYPE = function() {}; // fake(虚假) Symbol
    $$typeof: REACT_ELEMENT_TYPE,
    type: type, // 记录节点类型,是原生组件还是class function Component or other
    key: key,
    ref: ref,
    props: props,

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

// ** createElement 源码
// 主要是对 props属性 的扩展;最终返回 ReactElement 的结果。
export function createElement(type, config, children) {
  let propName;
  const props = {};
  
  // 下面这四个值,是根据 config的内容 进行获取的,若没有对应的值,则以null返回。
  let key = null;
  let ref = null;
  let self = null;
  let source = null;
  
  // 注意 这里对 ref, key 是单独处理,赋予一个全新的变量。
  if (config != null) {
  	if (hasValidRef(config)) { // 判断 ref 是否有效
      ref = config.ref;
    }
    if (hasValidKey(config)) { // 判断 key 是否有效
      key = '' + config.key;
    }
    // config中其余的 属性 则添加到新props对象中
    for (propName in config) {
        props[propName] = config[propName] // config去除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];
    };
    {
       //冻结array 返回原来的childArray且不能被修改 防止有人修改库的核心对象 冻结对象大大提高性能
       if (Object.freeze) {
          Object.freeze(childArray);
       }
    }
    props.children = childArray; //父组件内部通过this.props.children获取子组件的值
    props.children = childArray;
  }

  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,
  );
}

猜你喜欢

转载自blog.csdn.net/qq_42387542/article/details/107667887
今日推荐