React16雖然出了一陣子了奕污。剛出來的時候姓蜂,粗略看了一遍更新文檔按厘。以為沒什么大的改動,也聽說項目從react15-16的升級過度可以很平滑钱慢,再加上項目改版上線一直比較頻繁逮京,所以一直還用的15.6的版本。
偶然在知乎看到@程墨Morgan大神的live束莫,便抱著好奇心和學習的心態(tài)報名了懒棉,受益良多草描。
我理解的Fiber架構:
改變了之前react的組件渲染機制,新的架構使原來同步渲染的組件現(xiàn)在可以異步化策严,可中途中斷渲染穗慕,執(zhí)行更高優(yōu)先級的任務。釋放瀏覽器主線程妻导,
1. 要理解Fiber架構逛绵,首先要理解react16以前,組建的渲染順序.
在我之前的一篇文章有簡單介紹倔韭,閱讀react源碼--記錄:1.1 問題記錄
下面從一個具體實例理解一下术浪,再加上我畫了圖,應該很好理解啦~(圖畫的有點渣)
假如有A,B,C,D組件寿酌,層級結構為:
我們知道組件的生命周期為:
掛載階段:
- constructor()
- componentWillMount()
- render()
- componentDidMount()
更新階段為: - componentWillReceiveProps()
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate
那么在掛載階段胰苏,A,B,C,D的生命周期渲染順序是如何的呢?
以render()函數(shù)為分界線醇疼。從頂層組件開始硕并,一直往下,直至最底層子組件秧荆。然后再往上倔毙。
組件update階段同理。
————————
前面是react16以前的組建渲染方式辰如。這就存在一個問題普监,
如果這是一個很大,層級很深的組件琉兜,react渲染它需要幾十甚至幾百毫秒,在這期間毙玻,react會一直占用瀏覽器主線程豌蟋,任何其他的操作(包括用戶的點擊,鼠標移動等操作)都無法執(zhí)行桑滩。
好似一個潛水員梧疲,當它一頭扎進水里,就要往最底層一直游运准,直到找到最底層的組件幌氮,然后他再上岸。在這期間胁澳,岸上發(fā)生的任何事该互,都不能對他進行干擾,如果有更重要的事情需要他去做(如用戶操作)韭畸,也必須得等他上岸
Fiber架構就是為了解決這個問題宇智。
看一下fiber架構 組建的渲染順序
潛水員會每隔一段時間就上岸蔓搞,看是否有更重要的事情要做。
加入fiber的react將組件更新分為兩個時期
-
phase 1
-
phase 2
這兩個時期以render為分界随橘,
render前的生命周期為phase1,
render后的生命周期為phase2
phase1的生命周期是可以被打斷的喂分,每隔一段時間它會跳出當前渲染進程,去確定是否有其他更重要的任務机蔗。此過程蒲祈,React 在 workingProgressTree (并不是真實的virtualDomTree)上復用 current 上的 Fiber 數(shù)據(jù)結構來一步地(通過requestIdleCallback)來構建新的 tree,標記處需要更新的節(jié)點萝嘁,放入隊列中讳嘱。
phase2的生命周期是不可被打斷的,React 將其所有的變更一次性更新到DOM上酿愧。
這里最重要的是phase1這是時期所做的事沥潭。因此我們需要具體了解phase1的機制。
- 如果不被打斷嬉挡,那么phase1執(zhí)行完會直接進入render函數(shù)钝鸽,構建真實的virtualDomTree
- 如果組件再phase1過程中被打斷,即當前組件只渲染到一半(也許是在willMount,也許是willUpdate~反正是在render之前的生命周期)庞钢,那么react會怎么干呢拔恰? react會放棄當前組件所有干到一半的事情,去做更高優(yōu)先級更重要的任務(當然基括,也可能是用戶鼠標移動颜懊,或者其他react監(jiān)聽之外的任務),當所有高優(yōu)先級任務執(zhí)行完之后风皿,react通過callback回到之前渲染到一半的組件河爹,從頭開始渲染。(看起來放棄已經(jīng)渲染完的生命周期桐款,會有點不合理咸这,反而會增加渲染時長,但是react確實是這么干的)
看到這里魔眨,相信聰明的同學已經(jīng)發(fā)現(xiàn)一些問題啦~
也就是 所有phase1的生命周期函數(shù)都可能被執(zhí)行多次媳维,因為可能會被打斷重來
這樣的話,就和react16版本之前有很大區(qū)別了遏暴,因為可能會被執(zhí)行多次侄刽,那么我們最好就得保證phase1的生命周期每一次執(zhí)行的結果都是一樣的,否則就會有問題朋凉,因此州丹,最好都是純函數(shù)。
(所以react16目前都沒有把fiber enable侥啤,其實react16還是以 同步的方式在做組建的渲染当叭,因為這樣的話茬故,很多我們用老版本react寫的組件就有可能都會有問題,包括用的很多開源組件,但是后面應該會enable,讓開發(fā)者可以開啟fiber異步渲染模式~)
對了蚁鳖,程墨大神還提到一個問題磺芭,饑餓問題,即如果高優(yōu)先級的任務一直存在醉箕,那么低優(yōu)先級的任務則永遠無法進行钾腺,組件永遠無法繼續(xù)渲染。這個問題facebook目前好像還沒解決讥裤,但以后會解決~
所以放棒,facebook在react16增加fiber結構,其實并不是為了減少組件的渲染時間己英,事實上也并不會減少间螟,最重要的是現(xiàn)在可以使得一些更高優(yōu)先級的任務,如用戶的操作能夠優(yōu)先執(zhí)行损肛,提高用戶的體驗厢破,至少用戶不會感覺到卡頓~