接上文,git
React流程圖:
https://bogdan-lyashenko.gith...github
componentMount是咱們重點關注對象之一。 這個方法最重要的部分就是ReactCompositeComponent.mountComponent.
若是你還有印象,我提到過第一個被壓入到組件樹裏的組件是TopLevelWrapper(React內部類)。在mountComponent中,咱們將掛載它。
可是,這個內部類是一個空的包裝類。對於調試來講毫無心義,它徹底不影響流程。因此,咱們暫且跳過它,先對它的子組件進行研究。app
掛載一個組件樹的過程大體以下:掛載父親組件,而後掛載它的子組件,而後是子組件的子組件,以此類推。當TopLevelWrapper掛載後,它的子組件(ReactCompositeComponent,負責管理ExampleApplication)也會進入到相同的步驟。svg
咱們回到ReactCompoiteComponent一探究竟。這裏面有一些關鍵點須要注意,接下去咱們會詳細的討論裏面的邏輯。函數
流程圖中 transaction.getUpdateQueue()返回的對象updateQueue,其實就是ReactUpdateQueue模塊。那麼會爲何在這裏要賦值updateQueue呢?這是由於ReactCompositeComponent(咱們正在研究的類)是各個平臺都須要使用的,可是updateQueue則在不一樣平臺有不一樣實現,因此須要咱們動態的在掛載過程當中根據不一樣的平臺賦予不一樣的值。this
目前咱們並不會使用updateQueue,可是咱們必須瞭解的是,updateQueue很是很是重要,大名鼎鼎的setState方法就會使用到這個updateQueue。調試
在這個階段,除了對updateQueue的賦值,還會有組件實例(自定義組件)被props,context,refs擴展的過程。code
看下以下代碼:component
// \src\renderers\shared\stack\reconciler\ReactCompositeComponent.js#255 // These should be set up in the constructor, but as a convenience for // simpler class abstractions, we set them up after the fact. inst.props = publicProps; inst.context = publicContext; inst.refs = emptyObject; inst.updater = updateQueue;
這個步驟以後,就能夠經過相似this.props的方式來讓實例獲取props等屬性了。對象
在流程圖中,經過調用_constructComponent方法和其餘幾個構造方式,一個新的ExampleApplication實例就被建立出來了。咱們在組件構造函數裏寫的代碼每每也是在這裏被調用的。 這裏,是咱們本身寫的代碼第一次真正被React系統調用的地方。
如今咱們開始掛載過程,第一件事就是調用componentWillMount(前提固然是若是有組件代碼裏有指定)。這個方法是咱們目前碰到的第一個生命週期事件鉤子。固然,在後面你也會看到componentDidMount方法。在這裏,咱們並不直接執行它們,咱們只是將它們押入到事務隊列裏。它們的真正的執行在很是後面,是在掛載操做完成以後才執行的。你能夠在componentWillMount裏調用setState方法,而後state會從新計算,可是render方法並不會被調用(若是在這裏調用render方法是毫無心義的,由於組件都沒掛載到DOM樹上呢)
官方文檔表達了相似的意思
當掛載事件發生前,componentWillMount方法會被馬上調用。它的調用在render方法以前,所以,在這裏調用setState不會觸發從新渲染(componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state in this method will not trigger a re-rendering.)
看下源碼裏是怎麼作的
// \src\renderers\shared\stack\reconciler\ReactCompositeComponent.js#476 if (inst.componentWillMount) { //.. inst.componentWillMount(); // When mounting, calls to `setState` by `componentWillMount` will set // `this._pendingStateQueue` without triggering a re-render. if (this._pendingStateQueue) { inst.state = this._processPendingState(inst.props, inst.context); } }
當state從新計算後,咱們就會調用render方法了,就是咱們在咱們自定義組件裏定義的render方法。React又一次使用了咱們的代碼。
接下去,咱們將會建立一個React組件實例,嗯,又建立一次。咱們以前已經調用過一次this._instantiateReactComponent了,爲何這裏又要調用一次呢?這是由於,前一次的調用,是建立一個ExampleApplication組件對應的ReactCompositeComponent實例,如今,咱們則是根據咱們組件的render方法中返回的元素,建立子組件對應的虛擬DOM實例。在咱們的列子中,render方法返回了一個div,因此,虛擬DOM建立一個ReactDOMComponent的實例。當這個實例建立後,咱們會又一次調用ReactReconciler.mountComponent方法,但此次是一個建立內部實例但過程,咱們傳遞的是一個ReactDOMComponent的實例。 而後,繼續調用它的mountComponent方法。。。(未完待續)