React源码解析之 createElement

696 阅读2分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

起步

  • github找到react官方代码,clone到自己本地。
  • 打开项目,在packages目录下找到react包,然后根据react目录下的package.json文件找到入口文件index.js,此时你可以看到如下所示:

image.png

  • 可以看到,从 ./src/React 文件下导出了我们在开发中用到的API
  • 接下来,我们进入 ./src/React所在文件
  • 在这个文件中可以看到,又是一堆文件引入和导出,总的来说这个文件可以理解成为一个中转站,如下图岁所示:

image.png

  • 接着,我们找到 createElement 所在文件,先了解它

createElement

image.png

  • 我们看到,createElement方法接收三个参数,最终返回了一个 ReactElemnt
  • 在该函数内部,我们可以看到做了这么几件事:
    • 对传入的config进行处理,把除了保留属性外的其他config赋值给props
    • 对传入的children进行处理,并将处理后的结果赋值给props.children (此处分了 children为一个节点和多个节点处理)
    • 对type.defaultProps进行处理,处理后将属性赋值给props
    • 最终调用ReactElement返回一个jsx对象

ReactElement

image.png

  • $$typeof表示的是组件的类型,例如在源码中有一个检查是否是合法Element的函数,就是根据object.$$typeof === REACT_ELEMENT_TYPE 来判断的
  • REACT_ELEMENT_TYPE 是在 shared/ReactSymbols 文件中,利用symbol来生成的标记react元素的类型的一个值。源码是这样的 REACT_ELEMENT_TYPE = symbolFor('react.element');
  • 上述代码中,if (__DEV__) {内部的一些操作},内部主要是使用 Object.deineProperty来给 element 对象 添加一些 属性值 不可修改的 属性

isValidElement

image.png

  • isValidElement 方法用来检验是否是一个reactElement类型

注意: 如果组件是ClassComponent则type是class本身,如果组件是FunctionComponent创建的,则type是这个function,源码中用ClassComponent.prototype.isReactComponent来区别二者。

注意: class或者function创建的组件一定要首字母大写,不然后被当成普通节点,type就是字符串。