面試官:說說react的渲染過程
hello,這里是瀟晨,大家在面試的過程中有沒有遇到過一些和react相關的問題呢,比如面試官讓你說說react渲染的過程,這到題目比較開放,也比較考驗大家對react渲染原理以及源碼的整體架構的理解。
-
整體流程:
react源碼3.1react的核心可以用ui=fn(state)來表示,更詳細可以用
const state = reconcile(update); const UI = commit(state);上面的fn可以分為如下一個部分:
- Scheduler(調度器): 排序優(yōu)先級,讓優(yōu)先級高的任務先進行reconcile
- Reconciler(協(xié)調器): 找出哪些節(jié)點發(fā)生了改變,并打上不同的Flags(舊版本react叫Tag)
- Renderer(渲染器): 將Reconciler中打好標簽的節(jié)點渲染到視圖上
那這些模塊是怎么配合工作的呢:
- 首先jsx經(jīng)過babel的ast詞法解析之后編程React.createElement,React.createElement函數(shù)執(zhí)行之后就是jsx對象,也被稱為virtual-dom。
- 不管是在首次渲染還是更新狀態(tài)的時候,這些渲染的任務都會經(jīng)過Scheduler的調度,Scheduler會根據(jù)任務的優(yōu)先級來決定將哪些任務優(yōu)先進入render階段,比如用戶觸發(fā)的更新優(yōu)先級非常高,如果當前正在進行一個比較耗時的任務,則這個任務就會被用戶觸發(fā)的更新打斷,在Scheduler中初始化任務的時候會計算一個過期時間,不同類型的任務過期時間不同,優(yōu)先級越高的任務,過期時間越短,優(yōu)先級越低的任務,過期時間越長。在最新的Lane模型中,則可以更加細粒度的根據(jù)二進制1的位置,來決定任務的優(yōu)先級,通過二進制的融合和相交,判斷任務的優(yōu)先級是否足夠在此次render的渲染。Scheduler會分配一個時間片給需要渲染的任務,如果是一個非常耗時的任務,如果在一個時間片之內沒有執(zhí)行完成,則會從當前渲染到的Fiber節(jié)點暫停計算,讓出執(zhí)行權給瀏覽器,在之后瀏覽器空閑的時候從之前暫停的那個Fiber節(jié)點繼續(xù)后面的計算,這個計算的過程就是計算Fiber的差異,并標記副作用。詳細可閱讀往期課件和視頻講解,往期文章在底部。
- 在render階段:render階段的主角是Reconciler,在mount階段和update階段,它會比較jsx和當前Fiber節(jié)點的差異(diff算法指的就是這個比較的過程),將帶有副作用的Fiber節(jié)點標記出來,這些副作用有Placement(插入)、Update(更新)、Deletetion(刪除)等,而這些帶有副作用Fiber節(jié)點會加入一條EffectList中,在commit階段就會遍歷這條EffectList,處理相應的副作用,并且應用到真實節(jié)點上。而Scheduler和Reconciler都是在內存中工作的,所以他們不影響最后的呈現(xiàn)。
- 在commit階段:會遍歷EffectList,處理相應的生命周期,將這些副作用應用到真實節(jié)點,這個過程會對應不同的渲染器,在瀏覽器的環(huán)境中就是react-dom,在canvas或者svg中就是reac-art等。
另外我們也可以從首次渲染和更新的時候看在render和commit這兩個子階段是如果工作的:
-
mount時:- 在
render階段會根據(jù)jsx對象構建新的workInProgressFiber樹,不太了解Fiber雙緩存的可以查看往期文章 Fiber架構,然后將相應的fiber節(jié)點標記為Placement,表示這個fiber節(jié)點需要被插入到dom樹中,然后會這些帶有副作用的fiber節(jié)點加入一條叫做Effect List的鏈表中。 - 在
commit階段會遍歷render階段形成的Effect List,執(zhí)行鏈表上相應fiber節(jié)點的副作用,比如Placement插入,或者執(zhí)行Passive(useEffect的副作用)。將這些副作用應用到真實節(jié)點上
- 在
-
update時:- 在
render階段會根據(jù)最新狀態(tài)的jsx對象對比current Fiber,再構建新的workInProgressFiber樹,這個對比的過程就是diff算法,diff算法又分成單節(jié)點的對比和多節(jié)點的對比,不太清楚的同學參見之前的文章 diff算法 ,對比的過程中同樣會經(jīng)歷收集副作用的過程,也就是將對比出來的差異標記出來,加入Effect List中,這些對比出來的副作用例如:Placement(插入)、Update(更新)、Deletion(刪除)等。 - 在
commit階段同樣會遍歷Effect List,將這些fiber節(jié)點上的副作用應用到真實節(jié)點上
- 在
react源碼3.2

