wangzhenggui/blog

react读源码系列之ReactElement

Opened this issue · 0 comments

前言

我们上节中说到了JSX到javaScript的一个编译过程,在当中我们知道了最后我们的组件和标签都会转换为React.createElement方法的“产物”,这一节我们就来说说这个产物到底是什么?

源码解读

我们在git上面下载react源码,react源码地址
我们打开ReactElement.js,找到React.createElement的方法实现

export function createElement(type, config, children) {
  // 处理参数

  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}

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
}

我们看见这个方法返回一个ReactElement对象,这个ReactElement对象就是上一节中所说的“产物”, 这一节我们就来聊聊这个ReactElement
我们先从方法的参数看起吧,createElement有3个参数 type, config, children

type: 指代这个ReactElement的类型

  • 字符串比如div,p代表原生DOM,称为HostComponent
  • Class类型是我们继承自Component或者PureComponent的组件,称为ClassComponent
  • 方法就是functional Component
  • 原生提供的Fragment、AsyncMode等是Symbol,会被特殊处理
  • TODO: 是否有其他的

config:我们在源码中可以看到,ref, key这俩个属性是直接绑定在组件上的,而不是放在props中的

children:源码中会对参数的个数进行获取,如果是3个参数,则props.children = 第三个参数,如果超过3个参数,则后面的参数都会合并成一个数组,props.children = 合并后的数组。所以我们在使用this.props.children这个属性的时候要注意他的数据结构

在来看看ReactElement这个函数吧!!

从上面可以看到这个函数的参数都是很眼熟,type,key, ref, props这些常见的这里就不陈述了,我们说一下$$typeof这个属性,这是个啥呢,在这里可以看出来他是一个常量:REACT_ELEMENT_TYPE,但有一个特例:ReactDOM.createPortal的时候是REACT_PORTAL_TYPE,不过他不是通过createElement创建的,所以他应该也不属于ReactElement

_owner这个属性表示这个ReactElement是哪个组件创建的,我理解这个可能在和解、组件更新的过程中会用到,这个后面遇到了再来说