React源码解析(二):组件的类型与生命周期

17,621 阅读3分钟

在上一篇文章《React源码解析(一):组件的实现与挂载》中,我们阐述了React组件的实现和挂载。现在我们来一起探究组件的生命周期。

我们已经知道,只有在挂载流程开始后,才会触发组件的生命周期,生成ReactElement类型的js对象,通过解析组件对象内部所携带的信息,获得对应的HTML信息,插入指定的DOM容器中,最终完成视图的渲染。那么组件的生命周期在这一过程中是如何触发的呢?

其实研究组件的声明周期,就是更深入的研究组件的挂载过程。

组件的生命周期

在上一篇文章的最后,我们知道ReactDOM.render()方法根据传入的参数不同,在内部通过工厂方法生成四种不同类型的封装组件:

  • ReactEmptyComponent
  • ReactTextComponent
  • ReactDOMComponent
  • ReactCompositeComponent

在执行挂载流程时,通过执行每种封装组件内部的mountComponent方法触发生命周期,但显然生命周期只在React自定义组件中存在,也就是ReactCompositeComponent。因为其他三种组件是不存在生命周期的,所以我们先来分析下相对容易的不存在生命周期的三种内部组件。

1.ReactEmptyComponent

通过ReactEmptyComponent.create()方法创建,该方法最终调用的是ReactDOMEmptyComponent方法,看下源码:

因为组件为空,所以几乎所有参数设置为null,也无关生命周期,只有组件的挂载和卸载。在关键方法mountComponent中,我们看到最终返回的是形如<!-->的HTML,也就是空,因此插入真实DOM的也是空。

2.ReactTextComponent

通过ReactHostComponent.createInstanceForText()方法创建,我们直接看mountComponent即可:

ReactDOMTextComponent相比ReactDOMEmptyComponent的处理稍微复杂一些,但是逻辑大致相同。escapeTextContentForBrowser方法内部对参数进行空格的校验处理,最终通过简单的' '+参数方法将参数转化为字符串并返回。

3.ReactDOMComponent

通过ReactHostComponent.createInternalComponent()方法创建,同样我们直接看mountComponent就好:

因为dom元素同样没有生命周期,ReactDOMComponent会对传入的div,span等标签通过switch进行识别和处理,除此之外流程与上述两类组件基本相同。

4.ReactCompositeComponent

自定义组件是React组件的重点,通过ReactCompositeComponentWrapper()方法创建,最终调用ReactCompositeComponentMixin.mountComponent方法创建组件的HTML。由于该函数非常长,感兴趣的读者请前往ReactCompositeComponent.js阅读源码,在此我们直接用图例给出该函数的逻辑:

基于以上,可以看出生命周期的执行的目的就是为了解析ReactElement获得HTML。由此我们更新上一篇文章中的四大组件类型的总结表格:

nextElement 实际参数 结果
null/false 创建ReactDOMEmptyComponent组件
object && type === string 虚拟DOM 创建ReactDOMComponent组件
object && type !== string React组件 创建ReactCompositeComponent组件
string 字符串 创建ReactDOMTextComponent组件
number 数字 创建ReactDOMTextComponent组件

最后基于第一篇文末给出的思维导图,我们进行细节完善: (点击可查看大图)

回顾:
《React源码解析(一):组件的实现与挂载》
《React源码解析(三):详解事务与更新队列》
《React源码解析(四):事件系统》
联系邮箱:ssssyoki@foxmail.com