React源碼系列之初次渲染

(本文說起代碼詳見ReactElement.js,這裏就不爲了好看而貼圖了)node

首先須要申明在React常常會提到的一些類型:ReactCompositeComponent是自定義組件(複合組件),ReactDOMComponent指的是瀏覽器自帶標籤,ReactDOMTextComponent是針對文本節點的。三者面向的類型不一樣,但它們的掛載方法都叫作mountComponent(React作了不少的抽象封裝,使各個函數功能可以處理各類結點等而不須要到處修改)。此外,咱們一般所說的Virtual DOM 是ReactElement,並經過ReactDOM的render方法渲染到真實DOM上。面試

那麼爲了實現渲染,究竟須要那些核心功能呢?瀏覽器

首先必定須要一個component類,用來表示組件在渲染、更新、刪除時應該作些什麼事情;而後須要一個component工廠方法,用來返回一個component實例(這樣就可使返回實例能夠屏蔽底層對具體類型的判斷和處理);另外須要mountComponent方法,用來在component渲染時生成DOM結構;最後還須要render方法做爲渲染的入口方法,內部經過事務來觸發掛載,將內容寫入對應的container中去。app

那麼具體來講,初次渲染是怎麼一個流程呢?又是怎麼利用這些核心功能的呢?函數

咱們知道React的虛擬DOM的概念,事實上,React.createElement就會建立一個這樣的虛擬DOM。在React.createElement方法中,會首先檢測config參數,而它包含着咱們在使用React組件時可能會傳入的ref、key(優化效率)、onClick等,此時ReactElement會將其保存爲內部屬性留與後用,而後,將其中的屬性傳入props保存,而且子元素children也會被保存到props。以後會調用ReactElement來返回虛擬DOM,而ReactElement貌似是個構造函數,實際上就是個工廠函數了,而且經過 $$typeof: REACT_ELEMENT_TYPE 來將其標記爲ReactElement。固然,若是打debugger調試的話,也會並不意外的發現這些方法會recursive的調用,下面將要提到的instantiateReactComponent 也是同樣,沒辦法,DOM樹就這樣嘛。(本段說起代碼詳見ReactElement.js)優化

由於有了ReactElement,就須要將其渲染出來,也就來到了instantiateReactComponent方法。這個方法本質上也是工廠函數,而且在內部會對須要render的node類型進行判斷,調用不一樣的方法來區別渲染。這樣對於render而言,就不須要關心具體類型了。固然一個有意思的點是,ReactCompositeComponentWrapper做爲ReactCompositeComponent的Wrapper,實際上就是assign了instantiateReactComponent方法,也就是說,對於不一樣的node,各自調用instantiateReactComponent就能夠渲染各自的component實例了。固然啦,像我此時試驗所用的<App />根組件就是返回的ReactCompositeComponentWrapper實例。spa

這裏繼續看ReactCompositeComponent。不妨看看performInitialMount方法,它會在內部會調用componentWillMount鉤子和_processPendingState,而後先將子ReactElement用_instantiateReactComponent渲染成child(ReactCompositeComponentWrapper),接着再將其用ReactReconciler.mountComponent渲染成一個Markup。事實上,這個調和器也是相似前面的工廠函數同樣,屏蔽了想要mount的component的類型,在內部仍舊統一調用了mountComponent,換句話說,Markup就是child.mountComponent。而Markup就是ReactDOMComponent,若是將其打印的話能夠看到,它就是那個準備被insertBefore到真實DOM樹的,哈哈。主要流程以下(其實仍是蠻簡化的,不過應該算是很重要的部分了吧)。debug

初次渲染主流程

在一篇文章上看到這樣的圖,相較而言更體現出instantiateReactComponent對不一樣元素類型的屏蔽,可是我畫的完整一點吧。可留做參考。調試

參考的文章裏的圖

最後,既然上面已經出現了componentWillMount,可知,在咱們終於要完成初次渲染的旅程時,必定會有componentDidMount,至於具體在哪,就不具體指出了。總之,如今想一想過去面試常被問的生命週期,真不是什麼上檔次的問題…component

後續會對更完整的更新機制進一步作探究。

相關文章
相關標籤/搜索