精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

亚洲va在线va天堂| 国产一区二区三区免费在线观看 | 国产视频在线观看网站| 黄色av网址在线| 三级成人在线视频| 免费成人高清视频| 亚洲综合自拍网| 婷婷激情成人| 狠狠躁天天躁日日躁欧美| 亚洲在线播放电影| 天天操天天干天天爱| 麻豆国产精品官网| 91精品国产高清自在线 | av中文在线观看| 亚洲一区二区三区四区五区午夜| 这里只有视频精品| 久久久久亚洲AV成人无码国产| 电影亚洲精品噜噜在线观看| 亚洲麻豆国产自偷在线| 欧美日韩一区综合| 亚洲AV无码乱码国产精品牛牛| 国产亚洲精品久| 97香蕉超级碰碰久久免费的优势| 国产三级短视频| 国产精品1luya在线播放| 欧美网站一区二区| 国产素人在线观看| 性欧美高清come| 中文字幕久久午夜不卡| 久久精品日韩精品| 精品国产免费无码久久久| 日韩中文字幕区一区有砖一区| 欧美激情喷水视频| 久草视频手机在线| 欧美日韩色图| 亚洲欧美制服第一页| 国产精品果冻传媒| 国产精品成人**免费视频| 日本久久电影网| 男女视频网站在线观看| 欧美精品videossex少妇| 亚洲特黄一级片| 亚洲一区二区在线看| 国产原创av在线| 久久只精品国产| 精品久久久久久一区| 亚洲黄色片视频| 国产一区二区三区综合| 成人黄色免费片| 中文字幕在线播放av| 久久xxxx精品视频| 成人av中文字幕| 最近2019中文字幕mv免费看| 日本少妇高潮喷水xxxxxxx| 欧美绝顶高潮抽搐喷水合集| 粉嫩嫩av羞羞动漫久久久| 成人福利视频在线观看| 亚洲天天综合网| 免费成人美女在线观看.| 国产成人精品电影| 中文人妻熟女乱又乱精品| 日韩vs国产vs欧美| 国产精品久久视频| 在线免费观看av片| 精品在线一区二区| 亚洲永久免费观看| 成人1区2区3区| 成人精品电影在线观看| 国产乱码精品一区二区三区卡 | 国产成人精品视频免费| 成人在线亚洲| 久久综合电影一区| 久久久久99精品成人片毛片| 亚洲性视频h| 欧美亚洲国产视频小说| 日韩黄色一级视频| 捆绑调教一区二区三区| 亚洲aⅴ日韩av电影在线观看 | 日韩高清国产精品| 日本成人在线播放| 亚洲精品老司机| 男人的天堂avav| 老色鬼在线视频| 色婷婷国产精品| 日本特黄a级片| 国产精品亚洲欧美一级在线| 日韩欧美在线观看一区二区三区| 精品无码人妻少妇久久久久久| 精品一区二区男人吃奶| 亚洲天堂男人天堂女人天堂| 欧美一级特黄高清视频| 国产精品九九| 国产mv久久久| 国产绿帽刺激高潮对白| 不卡的看片网站| 日本精品一区| 国产精品一卡二卡三卡 | 蜜臀av.com| 精精国产xxxx视频在线野外| 欧美影院一区二区三区| 亚洲三级在线视频| 同性恋视频一区| 日韩亚洲欧美中文高清在线| 青娱乐在线视频免费观看| 亚洲一区区二区| 成人性生交大片免费看视频直播| 免费观看成年人视频| 中文字幕免费在线观看视频一区| 特级西西人体www高清大胆| 国产激情在线播放| 91精品国产福利在线观看| 特级西西人体4444xxxx| 中文在线播放一区二区| 日韩美女福利视频| 国产av一区二区三区精品| av成人在线电影| 亚洲天堂最新地址| 亚洲一级二级| 国产欧美日韩专区发布| 欧洲综合视频| 亚洲一区二区三区视频在线播放| mm1313亚洲国产精品无码试看| 日本免费精品| 中文字幕日韩av电影| 日本中文字幕免费| 国产麻豆精品95视频| 视频一区二区三区免费观看| 大桥未久在线视频| 欧美一个色资源| 亚洲aaa视频| 日韩成人av影视| 伊人精品视频| 色青青草原桃花久久综合 | 狠狠躁狠狠躁视频专区| 欧美美女黄色| 欧美富婆性猛交| 国产又粗又大又爽| 中文字幕av不卡| 欧在线一二三四区| 亚洲精品国模| 欧美亚洲国产视频小说| 日本高清视频www| 一区二区三区欧美久久| 91亚洲精品久久久蜜桃借种| 欧美一二区在线观看| 国产97色在线|日韩| 日本国产在线| 欧美日韩性视频| 亚洲色偷偷色噜噜狠狠99网| 欧美日韩国产探花| 成人综合色站| 18video性欧美19sex高清| 日韩精品一区二区三区视频播放| 91视频青青草| 国产在线播放一区三区四| 亚洲图片都市激情| 欧美亚洲综合视频| 日韩视频精品在线| 国产麻豆免费视频| 亚洲免费观看在线视频| 成人在线短视频| 红桃视频国产精品| 国产区二精品视| 国产在线88av| 亚洲欧美国产va在线影院| 亚洲va男人天堂| 中国女人真人一级毛片| 国产日本欧洲亚洲| 人人干人人干人人| 99免费精品| 波多野结衣成人在线| 污污网站在线看| 亚洲精品国产精品国自产在线| 日本五十路女优| 久久伊人蜜桃av一区二区| 性欧美极品xxxx欧美一区二区| 欧美色女视频| 99r国产精品视频| 欧美一级鲁丝片| 伊人激情综合网| 99久久精品免费看国产交换| 亚洲国产裸拍裸体视频在线观看乱了 | 国产精品永久免费在线| 免费av在线网址| 欧美大片拔萝卜| 六月丁香激情综合| 欧美国产1区2区| 少妇欧美激情一区二区三区| 国产午夜精品一区二区三区欧美| 日产中文字幕在线精品一区| 四虎视频在线精品免费网址| 久久久久久综合网天天| 免费一级毛片在线观看| 911精品国产一区二区在线| 日韩xxxxxxxxx| 国产夜色精品一区二区av| 一二三级黄色片| 99精品视频免费观看| 四虎永久在线精品免费一区二区| 日韩欧美高清一区二区三区| 国产成人精品网站| 宅男在线观看免费高清网站| 亚洲欧美国产精品| 亚洲精品无码久久久| 欧美专区日韩专区| 亚洲精品在线观看av| 久久久国产精华| 女女调教被c哭捆绑喷水百合| 日韩激情在线观看| 欧美亚洲黄色片| 国产精品久久久久蜜臀| 欧美精品v日韩精品v国产精品| 精品国产不卡一区二区| 青青草精品毛片| 色婷婷在线播放| 中文字幕亚洲综合久久| 无码国产精品96久久久久| 欧美一级艳片视频免费观看| 亚洲av人无码激艳猛片服务器| 亚洲高清一区二区三区| 少妇高潮在线观看| 久久伊人中文字幕| 第四色在线视频| 国产iv一区二区三区| 成 人 黄 色 小说网站 s色| 天堂资源在线中文精品| 国产3p露脸普通话对白| 欧美一区不卡| 干日本少妇视频| 国产又粗又大又爽视频| 粉嫩一区二区三区性色av| 最新免费av网址| 蜜臀av性久久久久av蜜臀妖精 | 黑人另类精品××××性爽| 日日骚久久av| 爱久久·www| 亚洲人成亚洲人成在线观看| 五月激情丁香婷婷| 亚洲成人激情图| 精品国产亚洲av麻豆| 欧美巨大另类极品videosbest | 人妻少妇无码精品视频区| 成年人国产精品| 蜜桃色一区二区三区| 国产在线观看免费一区| 一区二区三区欧美精品| 免费不卡在线观看| 欧美婷婷精品激情| 青青草精品视频| 天堂中文视频在线| 日韩vs国产vs欧美| 九九视频精品在线观看| 日韩激情视频网站| 超碰在线97免费| 免费高清成人在线| 中文字幕成人在线视频| 另类中文字幕网| 五月天婷婷在线观看视频| 国产在线看一区| 成人三级做爰av| 成人国产免费视频| 久久精品综合视频| 国产午夜亚洲精品不卡 | 亚洲激情六月丁香| 精品无码人妻一区二区三区| 亚洲一区二区三区四区不卡| 日韩污视频在线观看| 欧美视频专区一二在线观看| 日韩中文字幕高清| 制服丝袜在线91| 亚洲毛片在线播放| 精品一区精品二区| 成年人视频在线观看免费| 色哟哟入口国产精品| 国产福利视频在线观看| 久久久久久久一区二区| 亚洲少妇视频| 国产精品综合久久久| 秋霞影院一区| 久久99热只有频精品91密拍| 欧美日韩精品一区二区视频| 中文字幕色一区二区| 黄页网站一区| 欧美日韩在线免费播放| 国产一二精品视频| 北岛玲一区二区| 中文字幕一区二区三区四区| 久久久久久久中文字幕| 一本一道综合狠狠老| 97精品人妻一区二区三区| 精品成人一区二区三区| 国产乱子伦三级在线播放| 欧美精品性视频| 欧美暴力调教| 成人av片网址| 精品国产一区二区三区久久久蜜臀 | 九九热免费精品视频| 国产麻豆成人精品| 蜜桃无码一区二区三区| 一区二区三区四区不卡在线| 香蕉影院在线观看| 日韩一区二区三区在线观看| 青青草视频免费在线观看| 久久久国产91| 欧美性理论片在线观看片免费| 亚洲自拍偷拍福利| 精品不卡一区| 国产无限制自拍| 久久99久久久久| 亚洲自拍偷拍一区二区| 亚洲无线码一区二区三区| 中文字幕乱码人妻二区三区| 亚洲国产日韩欧美综合久久| 免费黄色电影在线观看| 97在线观看免费| 激情视频亚洲| 亚洲精品白虎| 视频一区视频二区中文字幕| 欧美激情 亚洲| 亚洲视频一区二区在线| 国产精品露脸视频| 日韩av网址在线观看| 18av在线播放| 国产一区二区香蕉| 精品国产一区二区三区四区| 国产深夜男女无套内射| 国产成人精品免费在线| 日本爱爱小视频| 欧美无乱码久久久免费午夜一区| 色就是色亚洲色图| 97精品国产97久久久久久| 麻豆一二三区精品蜜桃| 一卡二卡3卡四卡高清精品视频| 天堂在线亚洲视频| 久久久久亚洲av无码专区桃色| 亚洲五码中文字幕| 亚洲欧美另类视频| 久久av资源网站| 国产一区2区在线观看| 视频在线精品一区| 视频一区在线视频| 性猛交ⅹxxx富婆video | 国产午夜一区二区三区| 探花视频在线观看| 亚洲美女在线看| 欧美日韩美女| 欧美高清性xxxxhdvideosex| 欧美亚洲视频| 日韩av一二区| 日韩欧美在线视频免费观看| 美国一级片在线免费观看视频| 26uuu另类亚洲欧美日本一| 欧美综合自拍| 成人一级片网站| 国产亚洲成年网址在线观看| 国产真人无遮挡作爱免费视频| 国产一区二区三区在线播放免费观看| 午夜精品久久久久久久久久蜜桃| 欧美日韩另类丝袜其他| 日韩在线播放一区二区| 黄色片网站免费| 欧美精品黑人性xxxx| 超碰在线最新| 国产精选在线观看91| 国产欧美日韩一级| 欧美人与性囗牲恔配| 欧美日韩国产首页在线观看| av电影免费在线观看| 国产精品久久久久久久小唯西川 | 久久久久久69| 欧美三级午夜理伦三级在线观看 | 欧美二区三区| 男男成人高潮片免费网站| 色老板免费视频| 欧美精品一区二区三区一线天视频| 白浆在线视频| 亚洲国产午夜伦理片大全在线观看网站 | 久久中文字幕在线| 精品国产乱子伦一区二区| 国产一级片黄色| 最新久久zyz资源站| 色哟哟中文字幕| 国产精品美女免费看| 欧美.日韩.国产.一区.二区| 午夜一区二区三区免费| 欧美久久久一区| gogo高清在线播放免费| 日本精品国语自产拍在线观看| 国产一区二区三区四区五区美女| 国产精品第72页| 一区二区国产精品视频| 美女国产精品久久久| 老熟妇仑乱视频一区二区| 亚洲免费观看高清完整版在线观看| 性一交一乱一伧老太| 国产99久久精品一区二区| 欧美在线黄色| 亚洲一区二区三区日韩 | 午夜福利一区二区三区| 国产精品日韩欧美|