自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:說說對React Fiber架構(gòu)的理解?解決了什么問題?

開發(fā) 前端
JavaScript引擎和頁面渲染引擎兩個線程是互斥的,當(dāng)其中一個線程執(zhí)行時,另一個線程只能掛起等待。

[[413974]]

本文轉(zhuǎn)載自微信公眾號「JS每日一題」,作者灰灰。轉(zhuǎn)載本文請聯(lián)系JS每日一題公眾號。

一、問題

JavaScript引擎和頁面渲染引擎兩個線程是互斥的,當(dāng)其中一個線程執(zhí)行時,另一個線程只能掛起等待

如果 JavaScript 線程長時間地占用了主線程,那么渲染層面的更新就不得不長時間地等待,界面長時間不更新,會導(dǎo)致頁面響應(yīng)度變差,用戶可能會感覺到卡頓

而這也正是 React 15 的 Stack Reconciler所面臨的問題,當(dāng) React在渲染組件時,從開始到渲染完成整個過程是一氣呵成的,無法中斷

如果組件較大,那么js線程會一直執(zhí)行,然后等到整棵VDOM樹計算完成后,才會交給渲染的線程

這就會導(dǎo)致一些用戶交互、動畫等任務(wù)無法立即得到處理,導(dǎo)致卡頓的情況

二、是什么

React Fiber 是 Facebook 花費兩年余時間對 React 做出的一個重大改變與優(yōu)化,是對 React 核心算法的一次重新實現(xiàn)。從Facebook在 React Conf 2017 會議上確認(rèn),React Fiber 在React 16 版本發(fā)布

在react中,主要做了以下的操作:

  • 為每個增加了優(yōu)先級,優(yōu)先級高的任務(wù)可以中斷低優(yōu)先級的任務(wù)。然后再重新,注意是重新執(zhí)行優(yōu)先級低的任務(wù)
  • 增加了異步任務(wù),調(diào)用requestIdleCallback api,瀏覽器空閑的時候執(zhí)行
  • dom diff樹變成了鏈表,一個dom對應(yīng)兩個fiber(一個鏈表),對應(yīng)兩個隊列,這都是為找到被中斷的任務(wù),重新執(zhí)行

從架構(gòu)角度來看,F(xiàn)iber 是對 React核心算法(即調(diào)和過程)的重寫

從編碼角度來看,F(xiàn)iber是 React內(nèi)部所定義的一種數(shù)據(jù)結(jié)構(gòu),它是 Fiber樹結(jié)構(gòu)的節(jié)點單位,也就是 React 16 新架構(gòu)下的虛擬DOM

一個 fiber就是一個 JavaScript對象,包含了元素的信息、該元素的更新操作隊列、類型,其數(shù)據(jù)結(jié)構(gòu)如下:

  1. type Fiber = { 
  2.   // 用于標(biāo)記fiber的WorkTag類型,主要表示當(dāng)前fiber代表的組件類型如FunctionComponent、ClassComponent等 
  3.   tag: WorkTag, 
  4.   // ReactElement里面的key 
  5.   keynull | string, 
  6.   // ReactElement.type,調(diào)用`createElement`的第一個參數(shù) 
  7.   elementType: any
  8.   // The resolved function/class/ associated with this fiber. 
  9.   // 表示當(dāng)前代表的節(jié)點類型 
  10.   type: any
  11.   // 表示當(dāng)前FiberNode對應(yīng)的element組件實例 
  12.   stateNode: any
  13.  
  14.   // 指向他在Fiber節(jié)點樹中的`parent`,用來在處理完這個節(jié)點之后向上返回 
  15.   return: Fiber | null
  16.   // 指向自己的第一個子節(jié)點 
  17.   child: Fiber | null
  18.   // 指向自己的兄弟結(jié)構(gòu),兄弟節(jié)點的return指向同一個父節(jié)點 
  19.   sibling: Fiber | null
  20.   index: number, 
  21.  
  22.   ref: null | (((handle: mixed) => void) & { _stringRef: ?string }) | RefObject, 
  23.  
  24.   // 當(dāng)前處理過程中的組件props對象 
  25.   pendingProps: any
  26.   // 上一次渲染完成之后的props 
  27.   memoizedProps: any
  28.  
  29.   // 該Fiber對應(yīng)的組件產(chǎn)生的Update會存放在這個隊列里面 
  30.   updateQueue: UpdateQueue<any> | null
  31.  
  32.   // 上一次渲染的時候的state 
  33.   memoizedState: any
  34.  
  35.   // 一個列表,存放這個Fiber依賴的context 
  36.   firstContextDependency: ContextDependency<mixed> | null
  37.  
  38.   mode: TypeOfMode, 
  39.  
  40.   // Effect 
  41.   // 用來記錄Side Effect 
  42.   effectTag: SideEffectTag, 
  43.  
  44.   // 單鏈表用來快速查找下一個side effect 
  45.   nextEffect: Fiber | null
  46.  
  47.   // 子樹中第一個side effect 
  48.   firstEffect: Fiber | null
  49.   // 子樹中最后一個side effect 
  50.   lastEffect: Fiber | null
  51.  
  52.   // 代表任務(wù)在未來的哪個時間點應(yīng)該被完成,之后版本改名為 lanes 
  53.   expirationTime: ExpirationTime, 
  54.  
  55.   // 快速確定子樹中是否有不在等待的變化 
  56.   childExpirationTime: ExpirationTime, 
  57.  
  58.   // fiber的版本池,即記錄fiber更新過程,便于恢復(fù) 
  59.   alternate: Fiber | null

三、如何解決

Fiber把渲染更新過程拆分成多個子任務(wù),每次只做一小部分,做完看是否還有剩余時間,如果有繼續(xù)下一個任務(wù);如果沒有,掛起當(dāng)前任務(wù),將時間控制權(quán)交給主線程,等主線程不忙的時候在繼續(xù)執(zhí)行

即可以中斷與恢復(fù),恢復(fù)后也可以復(fù)用之前的中間狀態(tài),并給不同的任務(wù)賦予不同的優(yōu)先級,其中每個任務(wù)更新單元為 React Element 對應(yīng)的 Fiber節(jié)點

實現(xiàn)的上述方式的是requestIdleCallback方法

window.requestIdleCallback()方法將在瀏覽器的空閑時段內(nèi)調(diào)用的函數(shù)排隊。這使開發(fā)者能夠在主事件循環(huán)上執(zhí)行后臺和低優(yōu)先級工作,而不會影響延遲關(guān)鍵事件,如動畫和輸入響應(yīng)

首先 React 中任務(wù)切割為多個步驟,分批完成。在完成一部分任務(wù)之后,將控制權(quán)交回給瀏覽器,讓瀏覽器有時間再進(jìn)行頁面的渲染。等瀏覽器忙完之后有剩余時間,再繼續(xù)之前 React 未完成的任務(wù),是一種合作式調(diào)度。

該實現(xiàn)過程是基于 Fiber節(jié)點實現(xiàn),作為靜態(tài)的數(shù)據(jù)結(jié)構(gòu)來說,每個 Fiber 節(jié)點對應(yīng)一個 React element,保存了該組件的類型(函數(shù)組件/類組件/原生組件等等)、對應(yīng)的 DOM 節(jié)點等信息。

作為動態(tài)的工作單元來說,每個 Fiber 節(jié)點保存了本次更新中該組件改變的狀態(tài)、要執(zhí)行的工作。

每個 Fiber 節(jié)點有個對應(yīng)的 React element,多個 Fiber節(jié)點根據(jù)如下三個屬性構(gòu)建一顆樹:

  1. // 指向父級Fiber節(jié)點 
  2. this.return = null 
  3. // 指向子Fiber節(jié)點 
  4. this.child = null 
  5. // 指向右邊第一個兄弟Fiber節(jié)點 
  6. this.sibling = null 

通過這些屬性就能找到下一個執(zhí)行目標(biāo)

參考文獻(xiàn)

https://juejin.cn/post/6926432527980691470

https://zhuanlan.zhihu.com/p/137234573

 

https://vue3js.cn/interview

 

責(zé)任編輯:武曉燕 來源: JS每日一題
相關(guān)推薦

2021-07-13 07:52:03

ReactHooks組件

2021-06-30 07:19:36

React事件機(jī)制

2021-07-07 08:36:45

React應(yīng)用場景

2021-05-31 10:35:34

TCPWebSocket協(xié)議

2021-07-12 08:35:24

組件應(yīng)用場景

2021-07-08 06:51:29

React函數(shù)組件

2021-06-07 09:41:48

NodeBuffer 網(wǎng)絡(luò)協(xié)議

2021-06-08 08:33:23

NodeStream數(shù)據(jù)

2025-03-11 09:19:53

2021-09-13 09:23:52

TypeScript命名空間

2021-06-10 07:51:07

Node.js循環(huán)機(jī)制

2021-10-29 09:40:21

設(shè)計模式軟件

2021-06-03 08:14:01

NodeProcessJavaScript

2021-06-04 07:55:30

Node Fs 操作

2020-08-03 07:38:12

單例模式

2021-08-09 07:47:40

Git面試版本

2021-11-25 10:18:42

RESTfulJava互聯(lián)網(wǎng)

2021-06-15 10:01:02

應(yīng)用系統(tǒng)軟件

2021-06-29 09:47:34

ReactSetState機(jī)制

2021-07-19 07:55:24

Redux中間件原理
點贊
收藏

51CTO技術(shù)棧公眾號