偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

[[437450]]

大家好,我卡頌。

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

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

什么是副作用

簡(jiǎn)易的React工作原理可以概括為:

1.觸發(fā)更新

2.render階段:計(jì)算更新會(huì)造成的副作用

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

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

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

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

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

Effects List

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

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

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

SubtreeFlags

在重構(gòu)之后,會(huì)將子節(jié)點(diǎn)的副作用冒泡到父節(jié)點(diǎn)的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é)點(diǎn)并執(zhí)行對(duì)應(yīng)操作。

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

Suspense

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

這個(gè)特性就是Suspense。

Suspense是v16就提供的功能,但v18之后,當(dāng)開啟并發(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會(huì)等待子孫組件中的異步請(qǐng)求完畢后再渲染,所以當(dāng)代碼運(yùn)行時(shí)頁面首先會(huì)渲染fallback:

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

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

新舊版React的差異

再回顧下開篇介紹的簡(jiǎn)易R(shí)eact工作原理:

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

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

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

控制臺(tái)還是會(huì)打印「Sibling effect」。

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

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

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

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

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

總結(jié)

今天我們又學(xué)到了一個(gè)React源碼小知識(shí)。

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

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

參考資料

[1]在線Demo:

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

 

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

2016-12-16 12:06:09

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

2012-01-05 09:26:56

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

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ù)

2017-04-24 16:44:41

寬帶千兆速度

2013-07-09 14:22:56

Windows 8.1

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

2023-04-19 15:30:00

OpenJDKJava

2022-11-03 09:46:08

2020-06-04 07:55:33

ReentrantLo Java

2020-05-06 09:10:46

AQS同步器CAS

2016-10-19 12:54:15

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

2011-09-26 10:13:02

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

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