接上文,git
React流程圖:
https://bogdan-lyashenko.gith...github
從流程圖裏能看出,React會遍歷dirtyComponents數組,並在事務中調用ReactUpdates.runBatchedUpdates。這個事務是個新事務。那麼爲何要這麼設計呢?數組
此事務的類型爲ReactUpdatesFlushTransaction,在此以前咱們已經提到過,咱們去看下其相應的包裝器以方便咱們理解這個事務具體完成什麼任務。代碼裏有以下注釋:安全
ReactUpdatesFlushTransaction包裝器會清空dirtyComponents數組,而且執行全部已經壓入隊列裏的更新操做,這些操做通常都是由過程後的處理方法壓入的(好比,commponentDidUpdate方法)(ReactUpdatesFlushTransaction’s wrappers will clear the dirtyComponents array and perform any updates enqueued by mount-ready handlers (i.e., componentDidUpdate))
咱們也驗證下是否代碼真的這樣運轉。該事務有兩個包裝器,NEST_UPDATES和UPDATE_QUEUEING。在事務的初始化階段,咱們會先把dirtyComponentsLength存儲起來,而後在關閉階段,React進行組件比較。在更新過程當中,極可能dirtyComponents組件都發生裏改變,因此,須要不止一次的運行flushBatchedUpdates方法。代碼比較直白,沒有什麼黑魔法。app
可是,這裏其實有個地方須要注意下,ReactUpdatesFlushTransaction覆蓋了Transaction.perform方法,之因此這麼作,是由於,執行更新時須要調用ReactReconcileTransacation裏的行爲(這個事務在掛載過程當中也使用到了,目的是爲了確保應用狀態安全)。因此,在ReactUpdatesFlushTransaction.perform方法的執行過程當中,ReactReconcileTransaction方法會被調用到,因此,就是把事務方法在包了一次。ssh
整個技術流程大概如此:svg
[NESTED_UPDATES, UPDATE_QUEUEING].initialize() [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].initialize() method -> ReactUpdates.runBatchedUpdates [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].close() [NESTED_UPDATES, UPDATE_QUEUEING].close()
在此文的最後,咱們會回到事務方法,在確認下事務是如何幫助方法完成的,但在此以前,咱們先確認下ReactUpdates.runBatchedUpdates的實現。(srcrendererssharedstackreconcilerReactUpdates.js#125)this
在執行以前的第一步,就是把dirtyComponets進行排序,如何排序呢?基於mount order這個字段進行排序(一個整數值,在組件實例化時被設置進組件),這個字段表明父組件(它們也最早掛載)先更新,子組件接下去更新,以此類推。下一步,React會對updateBatchNumber加1操做,這個字段相似於當前處理DOM的ID,看下代碼裏的註釋,看下代碼裏的註釋:設計
在更新過程當中加入隊列的更新必須在批量操做執行完後再執行。不然,假設dirtyComponents爲有組件A,B,其中A的子組件爲B,B有子組件C,若是C有更新,則B將再次被壓入隊列,致使B被更新兩次。對於這種狀況,咱們只能經過檢查批量更新的計數器來跳過此次更新。(‘Any updates enqueued while reconciling must be performed after this entire batch. Otherwise, if dirtyComponents is [A, B] where A has children B and C, B could update twice in a single batch if C’s render enqueues an update to B (since B would have already updated, we should skip it, and the only way we can know to do so is by checking the batch counter).’)
這個設計避免了同一個組件的重複更新。code
最後,咱們遍歷完整個dirtyComponents隊列,而後把每一個組件傳遞給了ReactReconciler.performUpdateIfNecessary,這個方法會在ReactCompisteCompoent裏被調用,因此,最終咱們又回到了ReactCompsiteComponet裏的updateComponet方法。如今,咱們能夠更深刻的研究下這個方法。
(未完待續)