亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

詳解使用React.memo()來優化函數組件的性能

2024-05-06 16:49:13
字體:
來源:轉載
供稿:網友

React核心開發團隊一直都努力地讓React變得更快。在React中可以用來優化組件性能的方法大概有以下幾種:

  • 組件懶加載(React.lazy(...)和<Suspense />)
  • Pure Component
  • shouldComponentUpdate(...){...}生命周期函數

本文還會介紹React16.6加入的另外一個專門用來優化函數組件(Functional Component)性能的方法: React.memo。

無用的渲染

組件是構成React視圖的一個基本單元。有些組件會有自己本地的狀態(state), 當它們的值由于用戶的操作而發生改變時,組件就會重新渲染。在一個React應用中,一個組件可能會被頻繁地進行渲染。這些渲染雖然有一小部分是必須的,不過大多數都是無用的,它們的存在會大大降低我們應用的性能。

看下面這個例子:

import React from 'react';class TestC extends React.Component {  constructor(props) {    super(props);    this.state = {      count: 0    }  }    componentWillUpdate(nextProps, nextState) {    console.log('componentWillUpdate')  }    componentDidUpdate(prevProps, prevState) {    console.log('componentDidUpdate')      }    render() {    return (      <div >      {this.state.count}      <button onClick={()=>this.setState({count: 1})}>Click Me</button>      </div>    );  }}export default TestC;

TestC組件有一個本地狀態count,它的初始值是0(state = {count: 0})。當我們點擊Click Me按鈕時,count的值被設置為1。這時候屏幕的數字將會由0變成1。當我們再次點擊該按鈕時,count的值還是1, 這時候TestC組件不應該被重新渲染,可是現實是這樣的嗎?

為了測試count重復設置相同的值組件會不會被重新渲染, 我為TestC組件添加了兩個生命周期函數: componentWillUpdate和componentDidUpdate。componentWillUpdate方法在組件將要被重新渲染時被調用,而componentDidUpdate方法會在組件成功重渲染后被調用。

在瀏覽器中運行我們的代碼,然后多次點擊Click Me按鈕,你可以看到以下輸出:

React.memo,優化,函數組件

我們可以看到'componentWillUpdate'和'componentWillUpdate'在每次我們點擊完按鈕后,都會在控制臺輸出來。所以即使count被設置相同的值,TestC組件還是會被重新渲染,這些就是所謂的無用渲染。

Pure Component/shouldComponentUpdate

為了避免React組件的無用渲染,我們可以實現自己的shouldComponentUpdate生命周期函數。

當React想要渲染一個組件的時候,它將會調用這個組件的shouldComponentUpdate函數, 這個函數會告訴它是不是真的要渲染這個組件。

如果我們的shouldComponentUpdate函數這樣寫:

shouldComponentUpdate(nextProps, nextState) {  return true    }

其中各個參數的含義是:

  • nextProps: 組件將會接收的下一個參數props
  • nextProps: 組件的下一個狀態state

因為我們的shouldComponentUpdate函數一直返回true,這就告訴React,無論何種情況都要重新渲染該組件。

可是如果我們這么寫:

shouldComponentUpdate(nextProps, nextState) {  return false}

因為這個方法的返回值是false,所以React永遠都不會重新渲染我們的組件。

因此當你想要React重新渲染你的組件的時候,就在這個方法中返回true,否則返回false?,F在讓我們用shouldComponentUpdate重寫之前的TestC組件:

import React from 'react';class TestC extends React.Component {  constructor(props) {    super(props);    this.state = {      count: 0    }  }    componentWillUpdate(nextProps, nextState) {    console.log('componentWillUpdate')  }    componentDidUpdate(prevProps, prevState) {    console.log('componentDidUpdate')  }    shouldComponentUpdate(nextProps, nextState) {    if (this.state.count === nextState.count) {      return false    }    return true  }    render() {    return (       <div>       { this.state.count }       <button onClick = {        () => this.setState({ count: 1 }) }> Click Me </button>       </div>    );  }}export default TestC;

我們在TestC組件里添加了shouldComponentUpdate方法,判斷如果現在狀態的count和下一個狀態的count一樣時,我們返回false,這樣React將不會進行組件的重新渲染,反之,如果它們兩個的值不一樣,就返回true,這樣組件將會重新進行渲染。

再次在瀏覽器中測試我們的組件,剛開始的界面是這樣的:

React.memo,優化,函數組件

這時候,就算我們多次點擊Click Me按鈕,也只能看到兩行輸出:

componentWillUpdate
componentDidUpdate

因為第二次點擊Click Me按鈕后count值一直是1,這樣shouldComponentUpdate一直返回false,所以組件就不再被重新渲染了。

那么如何驗證后面state的值發生改變,組件還是會被重新渲染呢?我們可以在瀏覽器的React DevTools插件中直接對TestC組件的狀態進行更改。具體做法是, 在Chrome調試工具中點擊React標簽,在界面左邊選中TestC組件,在界面的右邊就可以看到其狀態state中只有一個鍵count,且其值是1:

React.memo,優化,函數組件

然后讓我們點擊count的值1,將其修改為2,然后按回車鍵:

React.memo,優化,函數組件

你將會看到控制臺有以下輸出:

componentWillUpdate
componentDidUpdate
componentWillUpdate
componentDidUpdate

state的count被改變了,組件也被重新渲染了。

現在讓我們使用另外一種方法PureComponent來對組件進行優化。

React在v15.5的時候引入了Pure Component組件。React在進行組件更新時,如果發現這個組件是一個PureComponent,它會將組件現在的state和props和其下一個state和props進行淺比較,如果它們的值沒有變化,就不會進行更新。要想讓你的組件成為Pure Component,只需要extends React.PureComponent即可。

讓我們用PureComponent去改寫一下我們的代碼吧:

import React from 'react';class TestC extends React.PureComponent {  constructor(props) {    super(props);    this.state = {      count: 0    }  }    componentWillUpdate(nextProps, nextState) {    console.log('componentWillUpdate')  }    componentDidUpdate(prevProps, prevState) {    console.log('componentDidUpdate')  }    /*shouldComponentUpdate(nextProps, nextState) {    if (this.state.count === nextState.count) {      return false    }    return true  }*/    render() {    return (       <div>       { this.state.count }       <button onClick = {        () => this.setState({ count: 1 })      }> Click Me </button>       </div >    );  }}export default TestC;

在上面的代碼中,我將shouldComponentUpdate的代碼注釋掉了,因為React.PureComponent本身就幫我們實現了一樣的功能。

改完代碼后,我們刷新一下瀏覽器,然后多次點擊Click Me按鈕看組件被渲染了多少遍:

React.memo,優化,函數組件

由上面的輸出可知,我們的component只在state由0變為1時被重新渲染了,后面都沒有進行渲染。

函數組件

上面我們探討了如何使用PureComponentshouldComponentUpdate的方法優化類組件的性能。雖然類組件是React應用的主要組成部分,不過函數組件(Functional Component)同樣可以被作為React組件使用。

function TestC(props) {  return (    <div>      I am a functional component    </div>  )}

對于函數組件,它們沒有諸如state的東西去保存它們本地的狀態(雖然在React Hooks中函數組件可以使用useState去使用狀態), 所以我們不能像在類組件中使用shouldComponentUpdate等生命函數去控制函數組件的重渲染。當然,我們也不能使用extends React.PureComponent了,因為它壓根就不是一個類。

要探討解決方案,讓我們先驗證一下函數組件是不是也有和類組件一樣的無用渲染的問題。

首先我們先將ES6的TestC類轉換為一個函數組件:

import React from 'react';const TestC = (props) => {  console.log(`Rendering TestC :` props)  return (     <div>      {props.count}    </div>  )}export default TestC;// App.js<TestC count={5} />

當上面的代碼初次加載時,控制臺的輸出是:

React.memo,優化,函數組件

同樣,我們可以打開Chrome的調試工具,點擊React標簽然后選中TestC組件:

React.memo,優化,函數組件

我們可以看到這個組件的參數值是5,讓我們將這個值改為45, 這時候瀏覽器輸出:

React.memo,優化,函數組件

由于count的值改變了,所以該組件也被重新渲染了,控制臺輸出Object{count: 45},讓我們重復設置count的值為45, 然后再看一下控制臺的輸出結果:

React.memo,優化,函數組件

由輸出結果可以看出,即使count的值保持不變,還是45, 該組件還是被重渲染了。

既然函數組件也有無用渲染的問題,我們如何對其進行優化呢?

解決方案: 使用React.memo()

React.memo(...)是React v16.6引進來的新屬性。它的作用和React.PureComponent類似,是用來控制函數組件的重新渲染的。React.memo(...) 其實就是函數組件的React.PureComponent。

如何使用React.memo(...)?

React.memo使用起來非常簡單,假設你有以下的函數組件:

const Funcomponent = ()=> {  return (    <div>      Hiya!! I am a Funtional component    </div>  )}

我們只需將上面的Funcomponent作為參數傳入React.memo中:

const Funcomponent = ()=> {  return (    <div>      Hiya!! I am a Funtional component    </div>  )}const MemodFuncComponent = React.memo(FunComponent)

React.memo會返回一個純化(purified)的組件MemoFuncComponent,這個組件將會在JSX標記中渲染出來。當組件的參數props和狀態state發生改變時,React將會檢查前一個狀態和參數是否和下一個狀態和參數是否相同,如果相同,組件將不會被渲染,如果不同,組件將會被重新渲染。

現在讓我們在TestC組件上使用React.memo進行優化:

let TestC = (props) => {  console.log('Rendering TestC :', props)  return (     <div>    { props.count }    </>  )}TestC = React.memo(TestC);

打開瀏覽器重新加載我們的應用。然后打開Chrome調試工具,點擊React標簽,然后選中<Memo(TestC)>組件。

接著編輯一下props的值,將count改為89,我們將會看到我們的應用被重新渲染了:

React.memo,優化,函數組件

然后重復設置count的值為89:

React.memo,優化,函數組件

這里沒有重新渲染!

這就是React.memo(...)這個函數牛X的地方!

在我們之前那個沒用到React.memo(...)的例子中,count的重復設置會使組件進行重新渲染。可是我們用了React.memo后,該組件在傳入的值不變的前提下是不會被重新渲染的。

結論

以下是幾點總結:

  • React.PureComponent是銀
  • React.memo(...)是金
  • React.PureComponent是給ES6的類組件使用的
  • React.memo(...)是給函數組件使用的
  • React.PureComponent減少ES6的類組件的無用渲染
  • React.memo(...)減少函數組件的無用渲染
  • 為函數組件提供優化是一個巨大的進步

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩在线观看免费av| 第一福利永久视频精品| 日本亚洲精品在线观看| 色综合影院在线| 精品久久久久久中文字幕大豆网| 国产一区二区三区日韩欧美| 热久久免费视频精品| 高潮白浆女日韩av免费看| 青青草国产精品一区二区| 中文字幕综合在线| 国产自产女人91一区在线观看| 亚洲精品国偷自产在线99热| 国产欧美va欧美va香蕉在| 国产精品久久久一区| 日韩久久精品成人| 亚洲国产三级网| 亚洲bt天天射| 91精品国产综合久久久久久蜜臀| 精品美女国产在线| 高清欧美性猛交| 欧美日韩中文字幕在线视频| 亚洲淫片在线视频| 91成人在线视频| 97在线视频一区| 欧美日韩亚洲高清| 亚洲精品国产综合久久| 亚洲欧美在线第一页| 国产一区二区三区在线播放免费观看| 亚洲人在线观看| 欧美极品少妇xxxxⅹ裸体艺术| 中文字幕视频在线免费欧美日韩综合在线看| 久久青草精品视频免费观看| 国产极品精品在线观看| 国内精品久久久久| 久久99精品视频一区97| 91精品国产九九九久久久亚洲| 欧美成人免费在线观看| 亚洲男人天堂2024| 91精品久久久久久久久久久久久| 97在线日本国产| 欧美午夜电影在线| 亚洲免费视频网站| 国产mv免费观看入口亚洲| 在线观看亚洲视频| 日韩天堂在线视频| 日本在线精品视频| 亚洲人成网站色ww在线| 久久久久久免费精品| 91九色综合久久| 日韩成人在线视频观看| 色多多国产成人永久免费网站| 亚洲欧美日韩在线一区| 成人精品在线视频| 91麻豆国产语对白在线观看| 91九色单男在线观看| 色香阁99久久精品久久久| 色噜噜狠狠狠综合曰曰曰| 有码中文亚洲精品| 国产精品久久久久久网站| 国内偷自视频区视频综合| 亚洲综合一区二区不卡| 精品国产福利视频| 亚洲视频在线免费观看| 日韩精品中文字幕在线播放| 国产日韩精品一区二区| 国产精品情侣自拍| 成人免费淫片视频软件| 日韩精品中文字幕在线观看| 国产精品稀缺呦系列在线| 亚洲国产黄色片| 日韩av中文字幕在线免费观看| 欧美电影免费看| 亚洲福利在线看| 国产精品久久久久久久9999| 久久久久久九九九| 亚洲国产另类久久精品| 亚洲经典中文字幕| 日韩性生活视频| 国产精品视频免费观看www| 久久精品亚洲94久久精品| 欧美国产日韩二区| 国产亚洲精品高潮| 日韩av免费网站| 九九视频这里只有精品| 欧美日韩在线免费观看| 日本伊人精品一区二区三区介绍| 亚洲区一区二区| 国色天香2019中文字幕在线观看| 青青青国产精品一区二区| 黄网站色欧美视频| 成人写真福利网| 欧美一区三区三区高中清蜜桃| 欧美激情一级欧美精品| 91精品啪aⅴ在线观看国产| 亚洲一区二区在线| 国产精品高精视频免费| 亚洲偷熟乱区亚洲香蕉av| 日韩女优人人人人射在线视频| 色综合亚洲精品激情狠狠| 日韩免费黄色av| 国产在线播放91| 欧美国产中文字幕| 尤物tv国产一区| 欧亚精品中文字幕| 国产在线视频欧美| 欧美午夜宅男影院在线观看| 欧美一区二粉嫩精品国产一线天| 97在线观看视频国产| 日韩国产一区三区| 国产精品成人一区| 精品动漫一区二区三区| 日本国产欧美一区二区三区| 亚洲欧美日韩精品久久亚洲区| 亚洲一区二区三区四区视频| 美女999久久久精品视频| 成人女保姆的销魂服务| 精品国产乱码久久久久酒店| 国产亚洲精品久久久久久777| 日韩精品视频在线播放| 日韩高清电影免费观看完整| 成人免费视频xnxx.com| 国产精品成av人在线视午夜片| 97在线看免费观看视频在线观看| 久久99国产精品自在自在app| 久久久女女女女999久久| 亚洲成人教育av| 国产欧美一区二区| 欧美一级片在线播放| 精品国产欧美成人夜夜嗨| 亚洲自拍小视频| 亚洲精品一区中文| 国产精品免费观看在线| 亚洲精品福利在线| 欧美精品18videos性欧美| 精品亚洲va在线va天堂资源站| 91免费精品国偷自产在线| 国产成人综合精品| 亚洲香蕉伊综合在人在线视看| 久久99亚洲精品| 欧美国产日韩二区| 成人精品久久一区二区三区| 亚洲欧洲在线免费| 日韩av有码在线| 91精品国产综合久久香蕉最新版| 成人免费高清完整版在线观看| 精品偷拍一区二区三区在线看| 日韩成人在线视频网站| 日韩av电影在线免费播放| 久久久久在线观看| 亚洲国产成人91精品| 国产精品吹潮在线观看| 久久综合色88| 欧美丰满少妇xxxxx做受| 亚洲欧美国产精品久久久久久久| 欧美一级成年大片在线观看| 在线看福利67194| 日韩视频永久免费观看| 日韩va亚洲va欧洲va国产| 国产欧美一区二区三区在线| 日韩av免费在线播放| 国产精品男人的天堂| …久久精品99久久香蕉国产| 综合欧美国产视频二区| 亚洲人成欧美中文字幕|