React原始碼解析(二):元件的型別與生命週期

ssssyoki發表於2017-11-06

在上一篇文章《React原始碼解析(一):元件的實現與掛載》中,我們闡述了React元件的實現和掛載。現在我們來一起探究元件的生命週期。

我們已經知道,只有在掛載流程開始後,才會觸發元件的生命週期,生成ReactElement型別的js物件,通過解析元件物件內部所攜帶的資訊,獲得對應的HTML資訊,插入指定的DOM容器中,最終完成檢視的渲染。那麼元件的生命週期在這一過程中是如何觸發的呢?

其實研究元件的宣告週期,就是更深入的研究元件的掛載過程。

元件的生命週期

在上一篇文章的最後,我們知道ReactDOM.render()方法根據傳入的引數不同,在內部通過工廠方法生成四種不同型別的封裝元件:

  • ReactEmptyComponent
  • ReactTextComponent
  • ReactDOMComponent
  • ReactCompositeComponent

在執行掛載流程時,通過執行每種封裝元件內部的mountComponent方法觸發生命週期,但顯然生命週期只在React自定義元件中存在,也就是ReactCompositeComponent。因為其他三種元件是不存在生命週期的,所以我們先來分析下相對容易的不存在生命週期的三種內部元件。

1.ReactEmptyComponent

通過ReactEmptyComponent.create()方法建立,該方法最終呼叫的是ReactDOMEmptyComponent方法,看下原始碼:

React原始碼解析(二):元件的型別與生命週期

因為元件為空,所以幾乎所有引數設定為null,也無關生命週期,只有元件的掛載和解除安裝。在關鍵方法mountComponent中,我們看到最終返回的是形如<!-->的HTML,也就是空,因此插入真實DOM的也是空。

2.ReactTextComponent

通過ReactHostComponent.createInstanceForText()方法建立,我們直接看mountComponent即可:

React原始碼解析(二):元件的型別與生命週期

ReactDOMTextComponent相比ReactDOMEmptyComponent的處理稍微複雜一些,但是邏輯大致相同。escapeTextContentForBrowser方法內部對引數進行空格的校驗處理,最終通過簡單的' '+引數方法將引數轉化為字串並返回。

3.ReactDOMComponent

通過ReactHostComponent.createInternalComponent()方法建立,同樣我們直接看mountComponent就好:

React原始碼解析(二):元件的型別與生命週期

因為dom元素同樣沒有生命週期,ReactDOMComponent會對傳入的div,span等標籤通過switch進行識別和處理,除此之外流程與上述兩類元件基本相同。

4.ReactCompositeComponent

自定義元件是React元件的重點,通過ReactCompositeComponentWrapper()方法建立,最終呼叫ReactCompositeComponentMixin.mountComponent方法建立元件的HTML。由於該函式非常長,感興趣的讀者請前往ReactCompositeComponent.js閱讀原始碼,在此我們直接用圖例給出該函式的邏輯:

React原始碼解析(二):元件的型別與生命週期

基於以上,可以看出生命週期的執行的目的就是為了解析ReactElement獲得HTML。由此我們更新上一篇文章中的四大元件型別的總結表格:

nextElement 實際引數 結果
null/false 建立ReactDOMEmptyComponent元件
object && type === string 虛擬DOM 建立ReactDOMComponent元件
object && type !== string React元件 建立ReactCompositeComponent元件
string 字串 建立ReactDOMTextComponent元件
number 數字 建立ReactDOMTextComponent元件

最後基於第一篇文末給出的思維導圖,我們進行細節完善: (點選可檢視大圖)

React原始碼解析(二):元件的型別與生命週期

回顧:
《React原始碼解析(一):元件的實現與掛載》
《React原始碼解析(三):詳解事務與更新佇列》
《React原始碼解析(四):事件系統》
聯絡郵箱:ssssyoki@foxmail.com

相關文章