成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

React Effects List大重構,是為了他?

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

[[437450]]

大家好,我卡頌。

本文我們來看React內部Effects List機制重構的前因后果。

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

什么是副作用

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

1.觸發更新

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

3.commit階段:執行副作用

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

  • Placement指DOM節點的插入與移動
  • Passive指useEffect回調執行
  • ChildDeletion指移除子DOM節點
  • 等等

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

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

Effects List

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

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

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

SubtreeFlags

在重構之后,會將子節點的副作用冒泡到父節點的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階段,再根據SubtreeFlags一層層查找有副作用的節點并執行對應操作。

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

Suspense

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

這個特性就是Suspense。

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

考慮如下組件:

  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并不是異步的!這里就體現了新舊版本React的差異。

新舊版React的差異

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

  • 觸發更新
  • render階段:協調器計算更新會造成的副作用
  • commit階段:渲染器執行副作用

在開啟并發之前,React保證一次render階段對應一次commit階段。

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

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

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

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

所以在新版中,針對Suspense內「不顯示的子樹」做了單獨的處理,既不會渲染display: none的內容,也不會執行useEffect回調:

要實現這部分處理的基礎,就是改變commit階段遍歷的方式,也就回到開篇提到的Effects List重構為subtreeFlags。

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

總結

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

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

未來他可能是實現React版keep-alive的基礎。

參考資料

[1]在線Demo:

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

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2012-01-05 09:26:56

App Store作產品賺錢

2016-12-16 12:06:09

數據分析大數據

2011-12-16 16:37:02

Fabrics邊界軟件數據中心

2023-10-20 10:09:44

人工智能

2013-03-08 09:54:25

2011-05-05 13:06:54

許小年企業轉型

2009-11-11 09:39:01

張汝京辭職

2015-08-13 17:45:08

七牛大數據

2013-07-09 14:22:56

Windows 8.1

2016-12-26 14:46:09

寬帶無線網絡Ovum

2017-04-24 16:44:41

寬帶千兆速度

2021-02-01 14:11:35

數字貨幣貨幣ATM

2017-09-20 14:10:04

大數據數據分析網紅店

2016-08-25 17:46:31

代碼組織CRM

2020-05-06 09:10:46

AQS同步器CAS

2020-06-04 07:55:33

ReentrantLo Java

2023-04-19 15:30:00

OpenJDKJava

2022-11-03 09:46:08

2016-10-19 12:54:15

數據聚類關聯

2011-09-26 10:13:02

微軟數據中心云計算
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 丝袜美腿一区二区三区 | 成人在线视频一区二区三区 | 久久久久精 | 天天射天天干 | 亚洲精品99| 亚洲成人精品一区二区 | 欧美精品一区二区免费 | 亚洲成色777777在线观看影院 | 久久999| 久久久精品一区二区三区四季av | 国产第二页 | 特黄色一级毛片 | 欧美视频在线观看 | 久久99网站| 精品精品 | 欧美日韩亚洲视频 | 亚洲国产精品一区二区www | 亚洲国产精品一区二区三区 | 午夜视频网 | 91 视频网站 | 91精品国产色综合久久 | 黄色亚洲| 午夜天堂精品久久久久 | 男女免费观看在线爽爽爽视频 | 久久久99精品免费观看 | 国产精品国产精品国产专区不卡 | 久久久看 | 亚欧洲精品在线视频免费观看 | 一区二区三区视频 | 99在线精品视频 | av手机免费在线观看 | 一区在线播放 | 国产精品成人69xxx免费视频 | 国产精品99久久久精品免费观看 | 欧洲亚洲精品久久久久 | 日韩欧美一区二区三区四区 | 欧美性成人 | 国产成人av电影 | 久久精品高清视频 | 国内精品视频在线 | 插插宗合网 |