React渲染機制整理


核心思想

ReactElement

Fiber

Current tree and Progress tree

ReactElement

什么是ReactElement,jsx通過babel轉化成React.createElement創造出來的數據結構,也就是通常所說的虛擬dom的數據結構(對象)

該數據結構通過$$typeof標識一個React元素,並且還有其他屬性props,key,ref等,最終以type表述該元素

Fiber

什么是Fiber節點,fiber概念是react在16版本之后增加的一個思想。

Fiber的誕生解決了react渲染到頁面出現的卡頓問題,新的渲染機制解決這個問題,但是舊的dom機制沒辦法實現。

在React中,每一個組件都會經歷create.CreateElement轉化成為ReactElement,在通過對每一個組件ReactElement生成了一個對應的Fiber節點,而這些節點將會

以鏈表的形式存放,形成了一個fiber節點的樹

Current true and Workinprogress tree

Fiber樹分為兩種,一種是當前頁面的樹,就是current tree,另外一顆樹是更新時候的生成的,根據當前current tree以及修改的一些參數生成的叫workInprogress樹

最終將workInProgress樹更新到頁面上,渲染之后此時的workInprogress樹變成current樹

React的渲染流程分為兩個階段

1.render階段

render階段開始是從renderRoot開始,在這個階段之前,是對fiber節點的初始化,初始化的根fiber節點含有firstUpdate,fristUpdate中element就是App的ReactElement

在React渲染過程中,整個fiber樹是從workLoop函數循環創建出來的

整個過程是深度遍歷

有兄弟節點,返回兄弟節點放入到workloop中進行循環

沒有兄弟節點,修改workInprogress樹的指向,指向當前fier節點的父級

沒有父級沒有兄弟節點,返回null workloop執行結束

整個過程生成workInprogress樹(已經更新的樹)同時生成一個effectList鏈表(收集變化的虛擬dom)

(ps:整個遍歷生成workInprogress過程中同時會標記副作用fiber node,effectlist會收集這些fiber node,effectlist在提交階段會映射到真是dom)

fiber之前的方案

因為fiber是采用鏈表結構,遍歷過程采用二叉樹深度優先遍歷復雜度(O(Log2|n)和O(n)之間,如果是平衡二叉樹則是O(Log2|n),從而達到了優化的對比的過程,而在老的版本,是采用遞歸方式遍歷兩顆樹復雜度(n)

遞歸的復雜度的由來是由於采用優化機制,即element diff component diff  tree diff

2.commit階段

執行完render階段,現在會有兩顆樹,current 樹根workInprogress樹

在commit階段會執行commitRoot函數,所有的生命周期,新增,刪除,更新組件都是在commitRoot中實現

commit階段主要工作是對真實dom的修改

更新dom不會重新遍歷整顆樹,而是通過循環整個effectlist鏈表來實現的,這樣保證了只針對變化的dom工作

commit三個階段

before mutation:讀取組件變更前的狀態class (getSnopshotBeforeUpdate)function(userEffect)

mutation:針對hostCompont進行相應操作,class(componentWillUnmunt)function (useEffect銷毀)

layout:操作dom完成之后class(componentDidMount)

workInprogress 樹切換到current樹也是在commit結束執行的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM