您當前的位置:首頁 > 旅遊

react原始碼解析7.Fiber架構

作者:由 zhanga222 發表于 旅遊時間:2022-10-26

react原始碼解析7。Fiber架構

影片講解(高效學習):進入學習

往期文章:

1。開篇介紹和麵試題

2。react的設計理念

3。react原始碼架構

4。原始碼目錄結構和除錯

5。jsx&核心api

6。legacy和concurrent模式入口函式

7。Fiber架構

8。render階段

9。diff演算法

10。commit階段

11。生命週期

12。狀態更新流程

13。hooks原始碼

14。手寫hooks

15。scheduler&Lane

16。concurrent模式

17。context

18事件系統

19。手寫迷你版react

20。總結&第一章的面試題解答

Fiber的深度理解

react15在render階段的reconcile是不可打斷的,這會在進行大量節點的reconcile時可能產生卡頓,因為瀏覽器所有的時間都交給了js執行,並且js的執行時單執行緒。為此react16之後就有了scheduler進行時間片的排程,給每個task(工作單元)一定的時間,如果在這個時間內沒執行完,也要交出執行權給瀏覽器進行繪製和重排,所以非同步可中斷的更新需要一定的資料結構在記憶體中來儲存工作單元的資訊,這個資料結構就是Fiber。

那麼有了Fiber這種資料結構後,能完成哪些事情呢,

工作單元 任務分解

:Fiber最重要的功能就是作為工作單元,儲存原生節點或者元件節點對應資訊(包括優先順序),這些節點透過指標的形似形成Fiber樹

增量渲染

:透過jsx物件和current Fiber的對比,生成最小的差異補丁,應用到真實節點上

根據優先順序暫停、繼續、排列優先順序

:Fiber節點上儲存了優先順序,能透過不同節點優先順序的對比,達到任務的暫停、繼續、排列優先順序等能力,也為上層實現批次更新、Suspense提供了基礎

儲存狀態:

因為Fiber能儲存狀態和更新的資訊,所以就能實現函式元件的狀態更新,也就是hooks

Fiber的資料結構

Fiber的自帶的屬性如下:

//ReactFiber。old。js

function

FiberNode

tag

WorkTag

pendingProps

mixed

key

null

|

string

mode

TypeOfMode

{

//作為靜態的資料結構 儲存節點的資訊

this

tag

=

tag

//對應元件的型別

this

key

=

key

//key屬性

this

elementType

=

null

//元素型別

this

type

=

null

//func或者class

this

stateNode

=

null

//真實dom節點

//作為fiber數架構 連線成fiber樹

this

return

=

null

//指向父節點

this

child

=

null

//指向child

this

sibling

=

null

//指向兄弟節點

this

index

=

0

this

ref

=

null

//用作為工作單元 來計算state

this

pendingProps

=

pendingProps

this

memoizedProps

=

null

this

updateQueue

=

null

this

memoizedState

=

null

this

dependencies

=

null

this

mode

=

mode

//effect相關

this

effectTag

=

NoEffect

this

nextEffect

=

null

this

firstEffect

=

null

this

lastEffect

=

null

//優先順序相關的屬性

this

lanes

=

NoLanes

this

childLanes

=

NoLanes

//current和workInProgress的指標

this

alternate

=

null

}

Fiber雙快取

現在我們知道了Fiber可以儲存真實的dom,真實dom對應在記憶體中的Fiber節點會形成Fiber樹,這顆Fiber樹在react中叫current Fiber,也就是當前dom樹對應的Fiber樹,而正在構建Fiber樹叫workInProgress Fiber,這兩顆樹的節點透過alternate相連。

function

App

()

{

return

<>

<

h1

>

<

p

>

count

<

/p> xiaochen

<

/h1>

<

/>

}

ReactDOM

render

<

App

/>

document

getElementById

“root”

));

react原始碼解析7.Fiber架構

構建workInProgress Fiber發生在createWorkInProgress中,它能建立或者服用Fiber

//ReactFiber。old。js

export

function

createWorkInProgress

current

Fiber

pendingProps

any

Fiber

{

let

workInProgress

=

current

alternate

if

workInProgress

===

null

{

//區分是在mount時還是在update時

workInProgress

=

createFiber

current

tag

pendingProps

current

key

current

mode

);

workInProgress

elementType

=

current

elementType

workInProgress

type

=

current

type

workInProgress

stateNode

=

current

stateNode

workInProgress

alternate

=

current

current

alternate

=

workInProgress

}

else

{

workInProgress

pendingProps

=

pendingProps

//複用屬性

workInProgress

type

=

current

type

workInProgress

flags

=

NoFlags

workInProgress

nextEffect

=

null

workInProgress

firstEffect

=

null

workInProgress

lastEffect

=

null

//。。。

}

workInProgress

childLanes

=

current

childLanes

//複用屬性

workInProgress

lanes

=

current

lanes

workInProgress

child

=

current

child

workInProgress

memoizedProps

=

current

memoizedProps

workInProgress

memoizedState

=

current

memoizedState

workInProgress

updateQueue

=

current

updateQueue

const

currentDependencies

=

current

dependencies

workInProgress

dependencies

=

currentDependencies

===

null

null

{

lanes

currentDependencies

lanes

firstContext

currentDependencies

firstContext

};

workInProgress

sibling

=

current

sibling

workInProgress

index

=

current

index

workInProgress

ref

=

current

ref

return

workInProgress

}

在mount時:會建立fiberRoot和rootFiber,然後根據jsx物件建立Fiber節點,節點連線成current Fiber樹。

react原始碼解析7.Fiber架構

在update時:會根據新的狀態形成的jsx(ClassComponent的render或者FuncComponent的返回值)和current Fiber對比形(diff演算法)成一顆叫workInProgress的Fiber樹,然後將fiberRoot的current指向workInProgress樹,此時workInProgress就變成了current Fiber。fiberRoot:指整個應用的根節點,只存在一個

fiberRoot:指整個應用的根節點,只存在一個 rootFiber:ReactDOM。render或者ReactDOM。unstable_createRoot創建出來的應用的節點,可以存在多個。

我們現在知道了存在current Fiber和workInProgress Fiber兩顆Fiber樹,Fiber雙快取指的就是,在經過reconcile(diff)形成了新的workInProgress Fiber然後將workInProgress Fiber切換成current Fiber應用到真實dom中,存在雙Fiber的好處是在記憶體中形成檢視的描述,在最後應用到dom中,減少了對dom的操作。

現在來看看Fiber雙快取建立的過程圖

mount時:

剛開始只建立了fiberRoot和rootFiber兩個節點

react原始碼解析7.Fiber架構

然後根據jsx建立workInProgress Fiber:

react原始碼解析7.Fiber架構

把workInProgress Fiber切換成current Fiber

react原始碼解析7.Fiber架構

update時

根據current Fiber建立workInProgress Fiber

react原始碼解析7.Fiber架構

把workInProgress Fiber切換成current Fiber

react原始碼解析7.Fiber架構

標簽: fiber  workInProgress  current  null  節點