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

React Effects List大重構(gòu),是為了他?

開發(fā) 前端
本文我們來看React內(nèi)部Effects List機制重構(gòu)的前因后果。你可以掌握React18對比之前版本,Suspense特性的差異及原因。

[[437450]]

大家好,我卡頌。

本文我們來看React內(nèi)部Effects List機制重構(gòu)的前因后果。

閱讀完本文,你可以掌握React18對比之前版本,Suspense特性的差異及原因。

什么是副作用

簡易的React工作原理可以概括為:

1.觸發(fā)更新

2.render階段:計算更新會造成的副作用

3.commit階段:執(zhí)行副作用

副作用包含很多類型,比如:

  • Placement指DOM節(jié)點的插入與移動
  • Passive指useEffect回調(diào)執(zhí)行
  • ChildDeletion指移除子DOM節(jié)點
  • 等等

更新造成DOM變化主要就是Placement、ChildDeletion在起作用。

那么render階段如何保存副作用,commit階段又是如何使用副作用的呢?

Effects List

在重構(gòu)前,render階段,帶有副作用的節(jié)點會連接形成鏈表,這條鏈表被稱為Effects List。

比如下圖,B、C、E存在副作用,連接形成Effects List:

commit階段不需要從A向下遍歷整棵樹,只需要遍歷Effects List就能找到所有有副作用的節(jié)點并執(zhí)行對應(yīng)操作。

SubtreeFlags

在重構(gòu)之后,會將子節(jié)點的副作用冒泡到父節(jié)點的SubtreeFlags屬性。

比如B、C、E包含的副作用如下圖:

冒泡流程如下:

  1. B的副作用為Passive,冒泡到A,A.SubtreeFlags包含Passive
  2. E的副作用為Placement,冒泡到D,D.SubtreeFlags包含Placement
  3. D冒泡到C,C.SubtreeFlags包含Placement
  4. C的副作用為Update,C.SubtreeFlags包含Placement,C冒泡到A
  5. 最終A.SubtreeFlags包含Passive、Placement、Update

這就代表A的子樹中包含這三種副作用。

在commit階段,再根據(jù)SubtreeFlags一層層查找有副作用的節(jié)點并執(zhí)行對應(yīng)操作。

可見,SubtreeFlags需要遍歷樹,而Effects List只需要遍歷鏈表,效率更高。那么React為什么要重構(gòu)呢?

Suspense

答案是:SubtreeFlags遍歷子樹的操作雖然比Effects List需要遍歷更多節(jié)點,但是React18中一種新特性恰恰需要「遍歷子樹」。

這個特性就是Suspense。

Suspense是v16就提供的功能,但v18之后,當開啟并發(fā)功能,Suspense與之前版本的行為是有區(qū)別的。

考慮如下組件:

  1. <Suspense fallback={<h3>loading...</h3>}> 
  2.   <LazyCpn /> 
  3.   <Sibling /> 
  4. </Suspense> 

其中LazyCpn是使用React.lazy包裹的異步加載組件。

Sibling代碼如下:

  1. function Sibling() { 
  2.   useEffect(() => { 
  3.     console.log("Sibling effect"); 
  4.   }, []); 
  5.  
  6.   return <h1>Sibling</h1>; 

由于Suspense會等待子孫組件中的異步請求完畢后再渲染,所以當代碼運行時頁面首先會渲染fallback:

  1. <h3>loading...</h3> 

但是Sibling并不是異步的!這里就體現(xiàn)了新舊版本React的差異。

新舊版React的差異

再回顧下開篇介紹的簡易React工作原理:

  • 觸發(fā)更新
  • render階段:協(xié)調(diào)器計算更新會造成的副作用
  • commit階段:渲染器執(zhí)行副作用

在開啟并發(fā)之前,React保證一次render階段對應(yīng)一次commit階段。

所以在上例中,雖然由于LazyCpn在請求導(dǎo)致Suspense渲染fallback,但是并不會阻止Sibling渲染,也不會阻止Sibling中useEffect的執(zhí)行。

控制臺還是會打印「Sibling effect」。

同時,為了在視覺上顯得Sibling沒有渲染,Sibling渲染的DOM節(jié)點會被設(shè)置display: none:

但這其實挺hack的。畢竟根據(jù)Suspense的理念,如果子孫組件有異步加載的內(nèi)容,那應(yīng)該只渲染fallback(而不是同時渲染display: none的內(nèi)容)

所以在新版中,針對Suspense內(nèi)「不顯示的子樹」做了單獨的處理,既不會渲染display: none的內(nèi)容,也不會執(zhí)行useEffect回調(diào):

要實現(xiàn)這部分處理的基礎(chǔ),就是改變commit階段遍歷的方式,也就回到開篇提到的Effects List重構(gòu)為subtreeFlags。

你可以從這個在線Demo[1]直觀的感受新舊版Suspense的差異

總結(jié)

今天我們又學到了一個React源碼小知識。

值得一提的是,針對Suspense的這次改進,為React帶來一種新的內(nèi)部組件類型 —— Offscreen Component。

未來他可能是實現(xiàn)React版keep-alive的基礎(chǔ)。

參考資料

[1]在線Demo:

https://codesandbox.io/s/frosty-currying-35olk?file=/src/App.js

 

責任編輯:姜華 來源: 魔術(shù)師卡頌
相關(guān)推薦

2012-01-05 09:26:56

App Store作產(chǎn)品賺錢

2016-12-16 12:06:09

數(shù)據(jù)分析大數(shù)據(jù)

2011-12-16 16:37:02

Fabrics邊界軟件數(shù)據(jù)中心

2023-10-20 10:09:44

人工智能

2013-03-08 09:54:25

2011-05-05 13:06:54

許小年企業(yè)轉(zhuǎn)型

2009-11-11 09:39:01

張汝京辭職

2015-08-13 17:45:08

七牛大數(shù)據(jù)

2013-07-09 14:22:56

Windows 8.1

2017-04-24 16:44:41

寬帶千兆速度

2016-12-26 14:46:09

寬帶無線網(wǎng)絡(luò)Ovum

2021-02-01 14:11:35

數(shù)字貨幣貨幣ATM

2017-09-20 14:10:04

大數(shù)據(jù)數(shù)據(jù)分析網(wǎng)紅店

2016-08-25 17:46:31

代碼組織CRM

2020-06-04 07:55:33

ReentrantLo Java

2022-11-03 09:46:08

2020-05-06 09:10:46

AQS同步器CAS

2023-04-19 15:30:00

OpenJDKJava

2016-10-19 12:54:15

數(shù)據(jù)聚類關(guān)聯(lián)

2011-09-26 10:13:02

微軟數(shù)據(jù)中心云計算
點贊
收藏

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