精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從Context源碼實現談React性能優化

開發 前端
這篇文章主要介紹Context的實現原理,源碼層面掌握React組件的render時機,從而寫出高性能的React組件,源碼層面了解shouldComponentUpdate、React.memo、PureComponent等性能優化手段的實現。

[[358779]]

 學完這篇文章,你會收獲:

  1. 了解Context的實現原理
  2. 源碼層面掌握React組件的render時機,從而寫出高性能的React組件
  3. 源碼層面了解shouldComponentUpdate、React.memo、PureComponent等性能優化手段的實現

我會盡量將文章寫的通俗易懂。但是,要完全理解文章內容,需要你掌握這些前置知識:

  1. Fiber架構的大體工作流程
  2. 優先級與更新在React源碼中的意義

組件render的時機

Context的實現與組件的render息息相關。在講解其實現前,我們先來了解render的時機。

換句話說,組件在什么時候render?

這個問題的答案,已經在React組件到底什么時候render啊聊過。在這里再概括下:

在React中,每當觸發更新(比如調用this.setState、useState),會為組件創建對應的fiber節點。

fiber節點互相鏈接形成一棵Fiber樹。

有2種方式創建fiber節點:

bailout,即復用前一次更新該組件對應的fiber節點作為本次更新的fiber節點。

render,經過diff算法后生成一個新fiber節點。組件的render(比如ClassComponent的render方法調用、FunctionComponent的執行)就發生在這一步。

經常有同學問:React每次更新都會重新生成一棵Fiber樹,性能不會差么?

React性能確實不算很棒。但如你所見,Fiber樹生成過程中并不是所有組件都會render,有些滿足優化條件的組件會走bailout邏輯。

比如,對于如下Demo:

  1. function Son() { 
  2.   console.log('child render!'); 
  3.   return <div>Son</div>; 
  4.  
  5.  
  6. function Parent(props) { 
  7.   const [count, setCount] = React.useState(0); 
  8.  
  9.   return ( 
  10.     <div onClick={() => {setCount(count + 1)}}> 
  11.       count:{count
  12.       {props.children} 
  13.     </div> 
  14.   ); 
  15.  
  16.  
  17. function App() { 
  18.   return ( 
  19.     <Parent> 
  20.       <Son/> 
  21.     </Parent> 
  22.   ); 
  23.  
  24. const rootEl = document.querySelector("#root"); 
  25. ReactDOM.render(<App/>, rootEl); 

 在線Demo地址[2]

點擊Parent組件的div子組件,觸發更新,但是child render!并不會打印。

這是因為Son組件會進入bailout邏輯。

bailout的條件

要進入bailout邏輯,需同時滿足4個條件:

1.oldProps === newProps

即本次更新的props全等于上次更新的props。

注意這里是全等比較。

我們知道組件render會返回JSX,JSX是React.createElement的語法糖。

所以render的返回結果實際上是React.createElement的執行結果,即一個包含props屬性的對象。

即使本次更新與上次更新props中每一項參數都沒有變化,但是本次更新是React.createElement的執行結果,是一個全新的props引用,所以oldProps !== newProps。

2.context value沒有變化

我們知道在當前React版本中,同時存在新老兩種context,這里指老版本context。

3.workInProgress.type === current.type

更新前后fiber.type不變,比如div沒變為p。

4.!includesSomeLane(renderLanes, updateLanes) ?

當前fiber上是否存在更新,如果存在那么更新的優先級是否和本次整棵Fiber樹調度的優先級一致?

如果一致代表該組件上存在更新,需要走render邏輯。

bailout的優化還不止如此。如果一棵fiber子樹所有節點都沒有更新,即使所有子孫fiber都走bailout邏輯,還是有遍歷的成本。

所以,在bailout中,會檢查該fiber的所有子孫fiber是否滿足條件4(該檢查時間復雜度O(1))。

如果所有子孫fiber本次都沒有更新需要執行,則bailout會直接返回null。整棵子樹都被跳過。

不會bailout也不會render,就像不存在一樣。對應的DOM不會產生任何變化。

老Context API的實現現

在我們大體了解了render的時機。有了這個概念,就能理解ContextAPI是如何實現的,以及為什么被重構。

我們先看被廢棄的老ContextAPI的實現。

Fiber樹的生成過程是通過遍歷實現的可中斷遞歸,所以分為遞和歸2個階段。

Context對應數據會保存在棧中。

在遞階段,Context不斷入棧。所以Concumer可以通過Context棧向上找到對應的context value。

在歸階段,Context不斷出棧。

那么老ContextAPI為什么被廢棄呢?因為他沒法和shouldComponentUpdate或Memo等性能優化手段配合。

shouldComponentUpdate的實現

要探究更深層的原因,我們需要了解shouldComponentUpdate的原理,后文簡稱其為SCU。

使用SCU是為了減少不必要的render,換句話說:讓本該render的組件走bailout邏輯。

剛才我們介紹了bailout需要滿足的條件。那么SCU是作用于這4個條件的哪個呢?

顯然是第一條:oldProps === newProps

當使用shouldComponentUpdate,這個組件bailout的條件會產生變化:

-- oldProps === newProps

++ SCU === false

同理,使用PureComponenet和React.memo時,bailout的條件也會產生變化:

-- oldProps === newProps

++ 淺比較oldProps與newsProps相等

回到老ContextAPI。

當這些性能優化手段:

使組件命中bailout邏輯

同時如果組件的子樹都滿足bailout的條件4

那么該fiber子樹不會再繼續遍歷生成。

換言之,不會再經歷Context的入棧、出棧。

這種情況下,即使context value變化,子孫組件也沒法檢測到。

新Context API的實現

知道老ContextAPI的缺陷,我們再來看新ContextAPI是如何實現的。

當通過:

  1. ctx = React.createContext(); 

創建context實例后,需要使用Provider提供value,使用Consumer或useContext訂閱value。

如:

  1. ctx = React.createContext(); 
  2.  
  3. const NumProvider = ({children}) => { 
  4.   const [num, add] = useState(0); 
  5.  
  6.   return ( 
  7.     <Ctx.Provider value={num}> 
  8.       <button onClick={() => add(num + 1)}>add</button> 
  9.       {children} 
  10.     </Ctx.Provider> 
  11.   ) 

使用:

  1. const Child = () => { 
  2.   const {num} = useContext(Ctx); 
  3.   return <p>{num}</p> 

  當遍歷組件生成對應fiber時,遍歷到Ctx.Provider組件,Ctx.Provider內部會判斷context value是否變化。

如果context value變化,Ctx.Provider內部會執行一次向下深度優先遍歷子樹的操作,尋找與該Provider配套的Consumer。

在上文的例子中會最終找到useContext(Ctx)的Child組件對應的fiber,并為該fiber觸發一次更新

注意這里的實現非常巧妙:

一般更新是由組件調用觸發更新的方法產生。比如上文的NumProvider組件,點擊button調用add會觸發一次更新。

觸發更新的本質是為了讓組件創建對應fiber時不滿足bailout條件4:

!includesSomeLane(renderLanes, updateLanes) ?

從而進入render邏輯。

在這里,Ctx.Provider中context value變化,Ctx.Provider向下找到消費context value的組件Child,為其fiber觸發一次更新。

則Child對應fiber就不滿足條件4。

這就解決了老ContextAPI的問題:

由于Child對應fiber不滿足條件4,所以從Ctx.Provider到Child,這棵子樹沒法滿足:

  • !! 子樹中所有子孫節點都滿足條件4

所以即使遍歷中途有組件進入bailout邏輯,也不會返回null,即不會無視這棵子樹的遍歷。

最終遍歷進行到Child,由于其不滿足條件4,會進入render邏輯,調用組件對應函數。

  1. const Child = () => { 
  2.   const {num} = useContext(Ctx); 
  3.   return <p>{num}</p> 

 在函數調用中會調用useContext從Context棧中找到對應更新后的context value并返回。

總結

React性能一大關鍵在于:減少不必要的render。

從上文我們看到,本質就是讓組件滿足4個條件,從而進入bailout邏輯。

而ContextAPI本質是讓Consumer組件不滿足條件4。

我們也知道了,React雖然每次都會遍歷整棵樹,但會有bailout的優化邏輯,不是所有組件都會render。

極端情況下,甚至某些子樹會被跳過遍歷(bailout返回null)。

參考資料

[1]React技術揭秘: http://react.iamkasong.com/

[2]在線Demo地址: https://codesandbox.io/s/quirky-chaplygin-5bx67?file=/src/App.js

 

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

2021-05-27 13:37:24

開發技能React

2021-08-27 14:26:06

開發技能React

2019-02-25 07:07:38

技巧React 優化

2022-08-03 09:11:31

React性能優化

2016-12-19 10:00:00

React性能優化

2023-11-01 17:57:56

React應用程序性能

2017-09-27 18:21:36

報表性能集算器

2023-11-01 11:59:13

2015-09-16 10:13:16

游戲性能

2009-06-29 15:39:53

Servlet和JSPServlet引擎

2020-06-22 07:30:00

React開發工具

2019-03-14 15:38:19

ReactJavascript前端

2023-07-03 07:51:47

2021-11-23 09:45:26

架構系統技術

2020-01-06 11:22:06

TCPLinux內核

2020-01-13 10:45:35

JavaScript解析前端

2019-09-18 08:53:55

2023-11-01 11:51:08

Linux性能優化

2025-04-02 07:29:14

2023-06-16 09:08:39

ReactContextRFC
點贊
收藏

51CTO技術棧公眾號

国产成人免费观看| 精品视频在线导航| 黄色录像特级片| 午夜久久久久久久久久| 国产一区二区三区的电影| 亚洲精品之草原avav久久| 啊啊啊国产视频| 日本一级理论片在线大全| 成人免费毛片嘿嘿连载视频| 57pao精品| 少妇真人直播免费视频| 国产91在线播放精品| 一区二区三区91| 鲁鲁视频www一区二区| 中文字幕在线网站| 亚洲高清在线| 色妞欧美日韩在线| 野战少妇38p| 成人在线免费电影网站| 亚洲3atv精品一区二区三区| 日韩欧美一区二区三区四区| 亚洲精品中文字幕成人片| 日韩国产欧美一区二区三区| 欧美精品一区三区| 国产91丝袜美女在线播放| 日本一区二区三区视频在线看| 欧美性极品少妇精品网站| 一区二区精品国产| 欧美视频免费一区二区三区| 国产大片一区二区| 国产精品偷伦视频免费观看国产 | 国产亚洲欧洲997久久综合| 91亚洲精品在线| 日韩精品一区二区亚洲av观看| 午夜精品偷拍| 色七七影院综合| 美女100%无挡| 欧美有码在线| 精品国产制服丝袜高跟| 国产探花在线看| 玛雅亚洲电影| 粉嫩av一区二区三区免费野| 黄网站色视频免费观看| 麻豆tv入口在线看| 国产精品青草久久| 日本在线观看一区二区| 欧美在线一卡| 91理论电影在线观看| 国产精品美女黄网| 亚洲精华国产精华精华液网站| 毛片av一区二区三区| 日韩免费在线免费观看| 69成人免费视频| 欧美激情成人在线| 国产成人免费视频网站| 日韩在线视频播放| 亚洲色图日韩精品| 日韩黄色大片| www.欧美免费| 国内毛片毛片毛片毛片毛片| 日韩电影免费在线观看| 国产一区二区三区在线看| 99久久久无码国产精品性| 色狼人综合干| 亚洲欧美中文在线视频| 国产人妻大战黑人20p| 精品盗摄女厕tp美女嘘嘘| 国产性猛交xxxx免费看久久| 亚洲av毛片基地| 欧美艳星介绍134位艳星| 一区二区福利视频| 特黄一区二区三区| 偷偷www综合久久久久久久| 久久精品99无色码中文字幕| 成人免费视频国产免费观看| 综合久久十次| 97精品国产aⅴ7777| 久久无码精品丰满人妻| 99日韩精品| 日韩av大片免费看| 伊人22222| 国产精品一二三四五| 国产另类第一区| 免费成人av电影| 一区在线播放视频| 日本成人性视频| heyzo中文字幕在线| 五月激情综合婷婷| 中文字幕网av| 精品一区91| 日韩精品中文字幕有码专区| www.久久av| 欧美国产一级| 色综合老司机第九色激情| 91看片在线播放| 日韩国产在线一| 99精彩视频在线观看免费| 天天干免费视频| 中文字幕第一页久久| 欧洲金发美女大战黑人| 老司机成人影院| 日韩欧美亚洲国产精品字幕久久久 | 国户精品久久久久久久久久久不卡| 久久免费少妇高潮久久精品99| 国产午夜性春猛交ⅹxxx| 另类综合日韩欧美亚洲| 国产精品入口免费| 在线视频二区| 五月天欧美精品| 岛国毛片在线播放| 亚洲毛片免费看| 久久亚洲精品一区二区| 精品无码一区二区三区电影桃花 | 国产精品欧美久久久久天天影视| www.激情成人| 亚洲欧洲精品一区二区| 女人让男人操自己视频在线观看| 6080国产精品一区二区| 人妻丰满熟妇aⅴ无码| 欧美福利电影在线观看| 国产精品久久久999| 天堂在线视频免费观看| 亚洲激情一二三区| 91女神在线观看| 亚洲伊人春色| 久久久久久亚洲精品不卡| 97超碰人人草| 欧美国产精品一区二区| 久久国产亚洲精品无码| 亚洲va欧美va人人爽成人影院| 在线播放日韩av| 日日噜噜噜噜人人爽亚洲精品| 国产 欧美在线| 大桥未久一区二区| 国产91欧美| 国产亚洲精品久久久优势| 欧美bbbbbbbbbbbb精品| 国产99久久久精品| 亚洲av首页在线| 日韩一级视频| 伊人一区二区三区久久精品| 天堂网免费视频| 久久免费美女视频| 日日碰狠狠添天天爽超碰97| 北条麻妃在线一区二区免费播放 | ririsao久久精品一区| 正在播放一区二区| 免费成人深夜蜜桃视频| 日本特黄久久久高潮| 欧洲一区二区日韩在线视频观看免费 | 久久视频这里有精品| 在线精品视频一区| 欧美高清第一页| 亚洲精品国偷拍自产在线观看蜜桃| 亚洲日本丝袜连裤袜办公室| 亚洲欧美日韩综合网| 欧美电影一二区| 亚洲aaa激情| 手机在线免费观看av| 欧美mv和日韩mv的网站| 欧洲猛交xxxx乱大交3| 国产很黄免费观看久久| 中文精品无码中文字幕无码专区 | 日韩黄色免费电影| 日韩欧美一区二区三区四区| 精品美女一区| 美女av一区二区| 亚洲高清视频在线播放| 精品国产乱码久久久久久天美 | 国产欧美一区二区精品忘忧草| 亚洲熟妇av一区二区三区 | 亚洲资源在线网| 香蕉成人在线| 欧美肥臀大乳一区二区免费视频| 丰满人妻一区二区三区免费视频 | 日韩三级一区二区| 欧美经典一区二区| 欧美第一页浮力影院| 在线成人激情| 黄色一区三区| 91九色综合| 欧美大奶子在线| 色一情一乱一区二区三区| 色综合久久九月婷婷色综合| 91无套直看片红桃在线观看| 国产传媒久久文化传媒| 玩弄中年熟妇正在播放| 欧美亚洲在线日韩| 96精品久久久久中文字幕| a级片免费在线观看| 国产亚洲xxx| 一级黄色大片免费观看| 亚洲在线中文字幕| 欧美图片第一页| 国产一区二区三区高清播放| 久久99中文字幕| 成人亚洲一区| 福利精品视频| 成人四虎影院| 国内精品中文字幕| 三区四区在线视频| 亚洲国产精品久久| 一区二区三区免费在线视频| 亚洲国产视频一区二区| 四季av中文字幕| 成人中文字幕在线| 九九热精品在线播放| 亚洲欧洲日本mm| 在线观看福利一区| 日韩精品福利一区二区三区| 成人网在线观看| 欧美momandson| 久久久久久有精品国产| 日本韩国在线视频爽| 亚洲成人网av| 国产成人毛毛毛片| 欧美综合欧美视频| 99热国产在线观看| 一区二区三区精品在线| 长河落日免费高清观看| 91一区一区三区| 一级黄色大片免费看| 日本美女一区二区三区视频| 成人一对一视频| 亚洲有吗中文字幕| 亚洲精品乱码久久久久久蜜桃91 | 丝袜美腿高跟呻吟高潮一区| av在线播放天堂| 亚洲综合五月| 亚洲一区三区视频在线观看| 欧美日韩激情| 免费成人av网站| 国产精品天天看天天狠| 91久久精品www人人做人人爽| 九九九精品视频| 国产精品av在线| 裤袜国产欧美精品一区| 91成人免费观看网站| 182在线播放| 欧美激情极品视频| av香蕉成人| 久久久精品美女| 在线免费观看的av网站| 亚洲人成在线电影| 免费黄网站在线观看| 国产丝袜一区二区三区| 性xxxxbbbb| 亚洲国产三级网| 国模无码一区二区三区| 欧美videofree性高清杂交| 国内老熟妇对白hdxxxx| 日韩一区二区电影| 国产wwwwwww| 日韩午夜激情电影| 丰满人妻av一区二区三区| 亚洲国产成人精品女人久久久| 成人毛片在线精品国产| 精品国产精品一区二区夜夜嗨 | 亚洲毛片在线免费观看| 午夜在线观看视频18| 亚洲精品久久久久久下一站 | 国产无套粉嫩白浆内谢| 性做久久久久久免费观看欧美| 日本在线小视频| 欧美日韩一区二区在线| 天堂网视频在线| 欧美在线观看一二区| 91福利在线观看视频| 欧美一区二区三区在线看| 动漫av一区二区三区| 日韩成人av网| av片在线看| 欧美另类在线播放| 国产夫妻在线播放| 国产精品v日韩精品| 日韩av黄色| 超碰在线观看97| 丝袜连裤袜欧美激情日韩| 日韩女优中文字幕| 日韩一区三区| 在线观看一区二区三区三州| 国产一区二区亚洲| 影音先锋男人的网站| 激情久久中文字幕| 老熟妇仑乱视频一区二区| 精品一区二区三区在线播放| 男人的天堂免费| 久久久噜噜噜久久人人看| 亚洲人与黑人屁股眼交| 亚洲一区日韩精品中文字幕| 无码人妻丰满熟妇奶水区码| 欧美日韩国产精品自在自线| 国产小视频免费观看| 亚洲人午夜精品| 中国av在线播放| 香蕉影视欧美成人| 激情五月开心婷婷| 日韩精品一级中文字幕精品视频免费观看| 国产一二三四在线视频| 国产精品99久久久久久有的能看 | 国产精品网站在线看| 日韩精品伦理第一区| 国产伊人精品| 四季av一区二区| 成人免费高清视频| 99热这里只有精品4| 香蕉成人伊视频在线观看| 在线观看一二三区| 亚洲国产99精品国自产| av一区在线观看| 97超级碰碰碰| 婷婷视频一区二区三区| 日韩福利视频| 99国内精品| 97免费公开视频| 国产精品国产三级国产普通话蜜臀| 99免费在线观看| 欧美一区二区二区| 欧美高清视频| 国产精品福利网站| 日韩在线麻豆| cao在线观看| 国产一区在线观看视频| 最新中文字幕av| 色中色一区二区| 五月激情六月婷婷| 久久久久久这里只有精品| 欧美影院视频| 亚洲免费av网| 免费人成精品欧美精品 | 国产精品美女久久久久久久久| 毛片毛片女人毛片毛片| 亚洲精品一区在线观看| 一色桃子av在线| 成人网中文字幕| 99久精品视频在线观看视频| 99久久国产宗和精品1上映| av网站一区二区三区| 五月天丁香激情| 91精品国产91久久久久久一区二区 | 人妻无码一区二区三区免费| 色悠久久久久综合欧美99| 五月天福利视频| 午夜精品久久久久久99热软件| 亚洲精品一二三**| 福利在线一区二区| 国产.欧美.日韩| 日韩欧美三级在线观看| 亚洲成av人乱码色午夜| av成人福利| 国产一区二区三区无遮挡| 亚洲乱亚洲高清| 六十路息与子猛烈交尾| 日韩一区精品视频| 一级黄色片播放| 日韩在线一区二区三区| 欧洲熟妇的性久久久久久| 一区二区三区在线观看动漫| 国产又粗又猛又爽又黄的视频一| 一区二区三区视频免费| 欧洲av一区二区| 亚洲看片网站| 国产做a爰片久久毛片| 九九热精品免费视频| 精品国产乱码久久久久久牛牛 | 精品日韩免费| 日日噜噜噜噜久久久精品毛片| 亚洲国产成人私人影院tom| 中文字字幕在线观看| 欧美精品手机在线| 久久久久久毛片免费看| 免费无码国产v片在线观看| 国产亚洲福利社区一区| 一级黄色片在线| 久久久久成人网| 久久99高清| 日韩在线一区视频| 亚洲国产综合色| 视频一区二区三区国产| 国产精品久久久久久久av电影| 天天射综合网视频| 亚洲午夜久久久久久久久| 色综合久久久久久久| 毛片在线视频| 精品久久久久久亚洲| 日产欧产美韩系列久久99| 久久人妻无码aⅴ毛片a片app| 欧美不卡视频一区| 高清不卡av| 一二三在线视频| 91浏览器在线视频| 国产精品欧美久久久久天天影视| 久久久久国产一区二区三区| 亚洲瘦老头同性70tv| 三级性生活视频| 欧美色视频日本版| 成码无人av片在线观看网站| 精品国产一区二区三区麻豆小说 | 俺去啦;欧美日韩| 色黄网站在线观看|