核心思想
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結束執行的。