// 源码 ReactElement.js
export function createElement(type, config, children) {
  // 处理参数

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

/**
type: 节点类型

原生节点 string
自己申明组件 classComponent funcitonComponent
使用react原生组件(Symbol,会被特殊处理)
  Fragment: REACT_FRAGMENT_TYPE,
  StrictMode: REACT_STRICT_MODE_TYPE,
  Suspense: REACT_SUSPENSE_TYPE,
*/

/**
config:写在jsx标签上的所有的attrs,以key-value形式存储

需要在config对象中筛选出我们认为是真正props内容以及特殊的key,ref属性
*/

/**
children:标签中间放置的一些内容
*/

/** 从源码可以看出虽然创建的时候都是通过config传入的,
但是key和ref不会跟其他config中的变量一起被处理,
而是单独作为变量出现在ReactElement上。
*/
// 源码 ReactElement.js
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
}

/**
$$typeof: 用来标识我们的Element是什么类型的

比如我们在写jsx代码的时候,所有的节点都是通过createElement创建的,那么它的$$typeof就永远是REACT_ELEMENT_TYPE,这点需要我们去记住。

因为,$$typeof在后续我们真正进行一个应用更新的时候,它如何渲染到dom的过程当中,它是经常要被用到的,它是用来一个判断的

大家可能会问了,我们写react应用的时候,大部分时间都是在写jsx,那么是不是所有的节点都是$$typeof?

也存在一些特殊情况,特殊情况和平台有关。在react-dom中,有个api叫React.createPortal,它返回的对象和上述类似,只不过它的$$typeof是REACT_PORTAL_TYPE
*/

/**
type: 记录节点类型,是原生组件还是class function Component or other
*/

小结:

ReactElement只是一个用来承载信息的容器,他会告诉后续的操作这个节点的以下信息:

type类型,用于判断如何创建节点
key和ref这些特殊信息
props新的属性内容
$$typeof用于确定是否属于ReactElement
这些信息对于后期构建应用的树结构是非常重要的,而React通过提供这种类型的数据,来脱离平台的限制

01-16 18:30