啥是React Fiber?
React Fiber,簡單來說就是一個從React v16開始引入的新協調引擎,用來實現Virtual DOM的增量渲染。
說人話:就是一種能讓React視圖更新過程變得更加流暢順滑的處理手法。
我們都知道:進程大,線程小。而Fiber(纖維)是一種比線程還要細粒度的處理機制。從這個單詞也可以猜測:React Fiber會很“細”。到底怎么個細法,我們接著往下看。
為什么會有React Fiber?
之前說了,React Fiber是為了讓React的視圖更新過程變得更加流暢順滑。怎么,之前React的視圖更新不流暢,不順滑了?
還真是的,在React v16之前,React的視圖更新確實存在很大的性能問題,其中首當其沖的,就是它的同步更新機制。
在React決定要加載或更新一顆組件樹之前,會大致做出如下一系列動作:調用各組件的生命周期函數 --> 計算和對比Virtual DOM --> 更新真實的DOM樹。這個過程是同步的,也就是說,一旦這個過程開始,它就會一鼓作氣跑完,一直到真實DOM樹更新完畢。
然而,當組件樹比較龐大時,這種機制的問題就來了:一顆擁有300個組件的組件樹需要全部更新,假設一個組件更新只需耗時1ms,整棵樹更新一次就需要耗時300ms。在這300ms期間,瀏覽器的主線程一直在“專心致志”地忙著更新這顆組件樹(這時函數的調用棧會非常長),對于頁面上的任何操作都是“不聞不問”的。在這期間,假如用戶在一個輸入框敲了幾個字,頁面上也不會有任何反應,因為渲染按鍵輸入結果也需要主線程來做,然而此時主線程正忙著更新組件樹呢。等到300ms結束了,瀏覽器主線程有空了,才把剛剛敲的那幾個字渲染到input輸入框內。
太卡了,真的。
由于JavaScript的單線程工作特點,業內一直有個這樣的原則:任何動作都不要長時間霸占主線程,如果遲遲不歸還主線程,那么在這期間程序就沒法對其他輸入作出響應。輸入了卻沒有響應,或者說響應來的很慢,也就是我們常常說的“卡頓”。顯然,React的同步更新機制在組件樹龐大時就違反了這一原則,犯了大忌。
這就是React Fiber出現的原因:為了解決舊版React視圖更新的性能瓶頸。
React Fiber到底怎么工作的?
首先,React Fiber并沒有解決更新龐大組件樹耗時長的問題,實際上總的耗時還是一樣的長。但是它解決了一個被廣大開發者口誅筆伐的惡行:長時間霸占主線程不放。
而它解決的方法就是:分片。
它的工作原理是這樣的:把耗時長的更新任務拆解成一個個小的任務分片,每執行完一個小的任務分片,都歸還一次主線程,看看有沒有什么其他緊急任務要做。如果在歸還主線程時恰巧發現有緊急任務,那么會馬上停掉當前更新任務,轉而讓主線程去做緊急任務,等主線程做完緊急任務,再重新做更新任務。(注意??:是重新!不是從上次被打斷的點繼續);如果沒有緊急任務,才敢唯唯諾諾地繼續做接下來的任務分片。
簡單來說,就是降了視圖更新的優先級,把更新過程碎片化。
現在我們捋一捋,React Fiber會這樣處理一個更新過程:
- 將一個更新過程分為Reconciliation階段和Commit階段,Reconciliation階段(調度階段)會更新數據并生成新的虛擬DOM,并且對新舊的虛擬DOM進行diff,得到需要更新的元素,放到新的更新隊列中;而Commit階段(渲染階段)則會遍歷更新隊列,并且將所有的變更一次性更新到真實DOM中;
- 對于Reconciliation階段進行分片處理,這個階段可以被更緊急的任務打斷,分片任務做到一半可能要重來;
- 對于Commit階段,直接一鼓作氣把DOM更新完,不能被打斷。
React Fiber的實現原理
React Fiber實現的難點有兩個:暫停/重啟如何實現?任務如何分散執行?
對于前者,暫停/重啟意味著我們需要保存狀態,這里在實現上用到了具有鏈表和指針的“單鏈表樹遍歷算法”,能夠記錄遍歷過程中的上一步和下一步。
而對于后者,則用到了requestAnimationFrame
和requestIdelCallback
這兩個API,其中requestAnimationFrame
是瀏覽器在每一幀都一定會執行的,可以放一些高優先級的任務;而requestIdelCallback
則是瀏覽器在一幀中最后如果有空閑時間才會去執行,可以放一些低優先級的任務,需要polyfill(因為兼容性不佳)。
React Fiber對我們日常開發有什么影響?
React Fiber在Reconciliation階段可能會調用以下生命周期函數(這也意味著在這個階段的生命周期函數在一次加載和更新過程中可能會被多次調用):
-
componentWillMount
-
componentWillUpdate
-
componentWillReceiveProps
-
shouldComponentUpdate
如果你恰巧沒有上react hooks的車,而是使用傳統的類組件進行開發,那么切記,不要在以上幾個生命周期函數中做只需要做一次的操作(比如:頁面初始化時發起一個ajax請求獲取數據)。
如果你平常使用react hooks進行開發,那沒事了,就當看了個熱鬧。
以上就是詳解React Fiber的工作原理的詳細內容,更多關于React Fiber的工作原理的資料請關注服務器之家其它相關文章!
原文鏈接:https://www.cnblogs.com/zhangnan35/p/14412197.html