前言:
在上篇文章React源碼解析之workLoop
中有提到 React 利用 childExpirationTime,來跳過子樹的遍歷及渲染,本文講下 childExpirationTime 的含義和做用。app
expirationTime 是如何產生的?
每當節點調用setState
,就會產生一個update
而且計算出一個expirationTime
(關於 expirationTime 的計算,請看:React源碼解析之ExpirationTime)oop
childExpirationTime 是如何產生的?post
因爲 React 的更新是從FiberRoot
開始的,因此當某一節點發生更新時,React 會向上遍歷,直至找到FiberRoot
。性能
在向上遍歷的過程當中,會順便找到發生更新節點的父節點,當找到父節點的時候,因爲它們的子節點發生了更新,因此會在父節點上設置childExpirationTime
3d
注意:
(1)多個子節點更新,取最大的expirationTime
做爲父節點的childExpirationTime
每一個父節點上只會有一個expirationTime
和一個childExpirationTime
,當有多個子節點都有更新時,取子節點最大的(優先級最高的)expirationTime
,做爲父節點的childExpirationTime
code
(2)單個子節點屢次更新,取某次更新出的最大的expirationTime
做爲自身的expirationTime
cdn
childExpirationTime 的做用?
在 React 自上而下更新 fiber 樹的時候,每一個節點會執行update
方法,根據expirationTime
和childExpirationTime
的優先級大小來判斷該節點自己、該節點的子節點是否須要在本次渲染(這一幀)的時候更新。對象
舉個例子:
上圖的List
產生的更新的expirationTime
爲 250(假設的,其實是個時間戳),Span1
的expirationTime
爲 100,Span2
的expirationTime
爲 200,明顯 Span2 的優先級高於 Span1,因此List
的childExpirationTime
設爲 200blog
其餘節點均無更新,expirationTime=NoWork
即 0,當 React 自上而下遍歷到List
節點時,發現它的 fiber 對象的expirationTime
大於childExpirationTime
,因此會優先執行List
自身的更新,若是這一幀留給 React 的時間還夠的話,會執行其子節點的更新,不然就跳過,放在下一幀執行rem
能夠想象,若是不設置childExpirationTime
的話,還要繼續向下遍歷獲取子節點的expirationTime
再拿去跟父節點的expirationTime
比較,看誰先更新,是浪費性能的作法。
(完)