国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
關鍵要點
React如何渲染UI
為什麼我們需要React記憶化
React中的記憶化
實現(xiàn)類組件中的記憶化
實現(xiàn)函數(shù)式組件中的記憶化
React.memo()對函數(shù)prop的問題
useCallback()以避免進一步重新渲染
注意事項
總結(jié)
關於React記憶化的常見問題解答(FAQ)
首頁 web前端 js教程 如何在REACT中實施回憶以提高性能

如何在REACT中實施回憶以提高性能

Feb 09, 2025 am 09:00 AM

How to Implement Memoization in React to Improve Performance

本教程將講解如何在React中實現(xiàn)記憶化(Memoization)。記憶化通過存儲昂貴函數(shù)調(diào)用的結(jié)果並在再次需要時返回這些緩存的結(jié)果來提高性能。

我們將涵蓋以下內(nèi)容:

  • React如何渲染UI
  • 為什麼需要React記憶化
  • 如何為函數(shù)式和類組件實現(xiàn)記憶化
  • 關於記憶化的注意事項

本文假設您已經(jīng)基本了解React中的類組件和函數(shù)式組件。如果您想複習這些主題,請查看官方React組件和props文檔。

How to Implement Memoization in React to Improve Performance

關鍵要點

  • React中的記憶化通過存儲昂貴函數(shù)調(diào)用的結(jié)果並在再次需要時返回這些緩存的結(jié)果來提高性能。
  • React使用虛擬DOM來高效地執(zhí)行DOM更新,但是對於大型組件,檢查虛擬DOM的性能影響可能很大。記憶化可以幫助避免不必要的重新渲染和虛擬DOM檢查。
  • React.PureComponentReact.memo()分別可用於在類組件和函數(shù)式組件中實現(xiàn)記憶化。如果組件的props或state沒有改變,這些方法可以防止不必要的重新渲染。
  • 如果一個函數(shù)作為prop傳遞給子組件,即使使用了React.memo(),子組件也會重新渲染。為了避免這種情況,可以使用useCallback()鉤子來防止每次父組件渲染時都重新創(chuàng)建函數(shù)。
  • 應該謹慎地在React應用程序中使用記憶化。當組件對相同的props返回相同的輸出、包含多個UI元素(虛擬DOM檢查會影響性能)或經(jīng)常提供相同的props時,它最有效。

React如何渲染UI

在詳細介紹React中的記憶化之前,讓我們首先看看React如何使用虛擬DOM渲染UI。

常規(guī)DOM基本上包含一組表示為樹的節(jié)點。 DOM中的每個節(jié)點都是UI元素的表示。每當應用程序中發(fā)生狀態(tài)更改時,該UI元素及其所有子元素的相應節(jié)點都會在DOM中更新,然後重新繪製UI以反映更新的更改。

借助高效的樹算法,更新節(jié)點的速度更快,但重新繪製速度較慢,並且當該DOM具有大量UI元素時,會對性能產(chǎn)生影響。因此,在React中引入了虛擬DOM。

這是真實DOM的虛擬表示。現(xiàn)在,每當應用程序的狀態(tài)發(fā)生任何變化時,React不會直接更新真實DOM,而是創(chuàng)建一個新的虛擬DOM。然後,React將這個新的虛擬DOM與先前創(chuàng)建的虛擬DOM進行比較,以查找需要重新繪製的差異。

使用這些差異,虛擬DOM將有效地用更改更新真實的DOM。這提高了性能,因為虛擬DOM不會簡單地更新UI元素及其所有子元素,而是有效地僅更新真實DOM中必要的最小更改。

為什麼我們需要React記憶化

在上一節(jié)中,我們看到了React如何使用虛擬DOM有效地執(zhí)行DOM更新以提高性能。在本節(jié)中,我們將查看一個用例,該用例解釋了為了進一步提高性能而需要記憶化的原因。

我們將創(chuàng)建一個父類,其中包含一個按鈕來遞增名為count的狀態(tài)變量。父組件還調(diào)用子組件,並將prop傳遞給它。我們還在兩個類的render方法中添加了console.log()語句:

//Parent.js
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState((prevState) => {
      return { count: prevState.count + 1 };
    });
  };

  render() {
    console.log("Parent render");
    return (
      <div className="App">
        <button onClick={this.handleClick}>Increment</button>
        <h2>Count: {this.state.count}</h2>
        <Child name={"joe"} />
      </div>
    );
  }
}

export default Parent;

此示例的完整代碼可在CodeSandbox上找到。

我們將創(chuàng)建一個Child類,該類接受父組件傳遞的prop並在UI中顯示它:

//Child.js
class Child extends React.Component {
  render() {
    console.log("Child render");
    return (
      <div>
        <h2>Name: {this.props.name}</h2>
      </div>
    );
  }
}

export default Child;

每當我們單擊父組件中的按鈕時,count值都會更改。由於這是一個狀態(tài)更改,因此會調(diào)用父組件的render方法。

傳遞給子類的props在每次父級重新渲染時都保持不變,因此子組件不應重新渲染。但是,當我們運行上述代碼並繼續(xù)遞增count時,我們會得到以下輸出:

<code>Parent render
Child render
Parent render
Child render
Parent render
Child render</code>

您可以在以下sandbox中自己遞增上述示例的count,並查看控制臺的輸出:

[此處應嵌入CodeSandbox鏈接,但由於我無法訪問外部網(wǎng)站,無法提供]

從這個輸出中,我們可以看到,當父組件重新渲染時,它也會重新渲染子組件——即使傳遞給子組件的props沒有改變。這將導致子組件的虛擬DOM與之前的虛擬DOM執(zhí)行差異檢查。由於子組件中沒有差異——因為props在所有重新渲染中都是相同的——因此不會更新真實的DOM。

我們確實具有不會不必要地更新真實DOM的性能優(yōu)勢,但我們可以在這裡看到,即使子組件沒有實際更改,也會創(chuàng)建新的虛擬DOM並執(zhí)行差異檢查。對於小型React組件,此性能可以忽略不計,但對於大型組件,性能影響很大。為了避免這種重新渲染和虛擬DOM檢查,我們使用記憶化。

React中的記憶化

在React應用程序的上下文中,記憶化是一種技術,其中,每當父組件重新渲染時,只有當props發(fā)生更改時,子組件才會重新渲染。如果props沒有更改,它不會執(zhí)行render方法,而是返回緩存的結(jié)果。由於render方法未執(zhí)行,因此不會創(chuàng)建虛擬DOM和差異檢查——從而提高了性能。

現(xiàn)在,讓我們看看如何在類和函數(shù)式React組件中實現(xiàn)記憶化以避免這種不必要的重新渲染。

(以下內(nèi)容與原文類似,只是對語言和表達方式進行了一些調(diào)整,並保持了圖片位置和格式不變。由於無法訪問外部網(wǎng)站,我無法提供CodeSandbox鏈接。)

實現(xiàn)類組件中的記憶化

要在類組件中實現(xiàn)記憶化,我們將使用React.PureComponent。 React.PureComponent實現(xiàn)了shouldComponentUpdate(),它對state和props進行淺比較,並且只有在props或state發(fā)生更改時才渲染React組件。

將子組件更改為如下所示的代碼:

//Parent.js
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState((prevState) => {
      return { count: prevState.count + 1 };
    });
  };

  render() {
    console.log("Parent render");
    return (
      <div className="App">
        <button onClick={this.handleClick}>Increment</button>
        <h2>Count: {this.state.count}</h2>
        <Child name={"joe"} />
      </div>
    );
  }
}

export default Parent;

此示例的完整代碼如下所示:[此處應嵌入CodeSandbox鏈接]

父組件保持不變?,F(xiàn)在,當我們在父組件中遞增count時,控制臺中的輸出如下:

//Child.js
class Child extends React.Component {
  render() {
    console.log("Child render");
    return (
      <div>
        <h2>Name: {this.props.name}</h2>
      </div>
    );
  }
}

export default Child;

對於第一次渲染,它會調(diào)用父組件和子組件的render方法。

在每次遞增的後續(xù)重新渲染中,只調(diào)用父組件的render函數(shù)。子組件不會重新渲染。

實現(xiàn)函數(shù)式組件中的記憶化

要在函數(shù)式React組件中實現(xiàn)記憶化,我們將使用React.memo()React.memo()是一個高階組件(HOC),它與PureComponent執(zhí)行類似的工作,避免不必要的重新渲染。

以下是函數(shù)式組件的代碼:

<code>Parent render
Child render
Parent render
Child render
Parent render
Child render</code>

我們還將父組件轉(zhuǎn)換為函數(shù)式組件,如下所示:

//Child.js
class Child extends React.PureComponent { // 將React.Component更改為React.PureComponent
  render() {
    console.log("Child render");
    return (
      <div>
        <h2>Name: {this.props.name}</h2>
      </div>
    );
  }
}

export default Child;

此示例的完整代碼可在以下sandbox中看到:[此處應嵌入CodeSandbox鏈接]

現(xiàn)在,當我們在父組件中遞增count時,控制臺會輸出以下內(nèi)容:

<code>Parent render
Child render
Parent render
Parent render</code>

React.memo()對函數(shù)prop的問題

在上面的示例中,我們看到當我們對子組件使用React.memo() HOC時,即使父組件也重新渲染,子組件也不會重新渲染。

但是,需要注意的一個小問題是,如果我們將函數(shù)作為prop傳遞給子組件,即使使用了React.memo(),子組件也會重新渲染。讓我們來看一個例子。

我們將更改父組件,如下所示。在這裡,我們添加了一個處理程序函數(shù),我們將其作為props傳遞給子組件:

//Child.js
export function Child(props) {
  console.log("Child render");
  return (
    <div>
      <h2>Name: {props.name}</h2>
    </div>
  );
}

export default React.memo(Child); // 在此處為子組件添加HOC以進行記憶化

子組件代碼保持不變。我們沒有使用作為props傳遞的函數(shù)在子組件中:

//Parent.js
import React, { useState } from 'react';
import Child from './Child';

export default function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  };
  console.log("Parent render");
  return (
    <div>
      <button onClick={handleClick}>Increment</button>
      <h2>Count: {count}</h2>
      <Child name={"joe"} />
    </div>
  );
}

現(xiàn)在,當我們在父組件中遞增count時,它會重新渲染並重新渲染子組件,即使props沒有更改。

那麼,是什麼導致子組件重新渲染的呢?答案是,每次父組件重新渲染時,都會創(chuàng)建一個新的處理程序函數(shù)並將其傳遞給子組件?,F(xiàn)在,由於處理程序函數(shù)在每次重新渲染時都會重新創(chuàng)建,因此子組件在對props進行淺比較時會發(fā)現(xiàn)處理程序引用已更改,並重新渲染子組件。

在下一節(jié)中,我們將看到如何解決此問題。

useCallback()以避免進一步重新渲染

導致子組件重新渲染的主要問題是處理程序函數(shù)的重新創(chuàng)建,這改變了傳遞給子組件的引用。因此,我們需要一種方法來避免這種重新創(chuàng)建。如果處理程序沒有重新創(chuàng)建,則對處理程序的引用不會更改——因此子組件不會重新渲染。

為了避免每次父組件渲染時都重新創(chuàng)建函數(shù),我們將使用一個名為useCallback()的React鉤子。鉤子是在React 16中引入的。要了解有關鉤子的更多信息,您可以查看React的官方鉤子文檔,或查看“React Hooks:如何入門和構建您自己的”。

useCallback()鉤子接受兩個參數(shù):回調(diào)函數(shù)和依賴項列表。

考慮以下useCallback()示例:

//Parent.js
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState((prevState) => {
      return { count: prevState.count + 1 };
    });
  };

  render() {
    console.log("Parent render");
    return (
      <div className="App">
        <button onClick={this.handleClick}>Increment</button>
        <h2>Count: {this.state.count}</h2>
        <Child name={"joe"} />
      </div>
    );
  }
}

export default Parent;

在這裡,useCallback()被添加到handleClick()函數(shù)中。第二個參數(shù)[x,y]可以是一個空數(shù)組、一個依賴項或一個依賴項列表。每當?shù)诙€參數(shù)中提到的任何依賴項發(fā)生更改時,才會重新創(chuàng)建handleClick()函數(shù)。

如果useCallback()中提到的依賴項沒有更改,則返回回調(diào)函數(shù)(作為第一個參數(shù))的記憶化版本。我們將更改我們的父函數(shù)式組件以對傳遞給子組件的處理程序使用useCallback()鉤子:

(此處與原文類似,只是對語言和表達方式進行了一些調(diào)整,並保持了圖片位置和格式不變。由於無法訪問外部網(wǎng)站,我無法提供CodeSandbox鏈接。)

注意事項

記憶化是通過避免在組件的props或state沒有更改時不必要地重新渲染組件來提高React應用程序性能的好技術。您可能會想到只為所有組件添加記憶化,但這並不是構建React組件的好方法。您應該僅在組件滿足以下條件時才使用記憶化:

  • 給定相同的props時返回相同的輸出
  • 具有多個UI元素,並且虛擬DOM檢查會影響性能
  • 經(jīng)常提供相同的props

總結(jié)

在本教程中,我們已經(jīng)看到了:

  • React如何渲染UI
  • 為什麼需要記憶化
  • 如何通過React.memo()為函數(shù)式React組件和React.PureComponent為類組件在React中實現(xiàn)記憶化
  • 一個用例,即使在使用React.memo()之後,子組件也會重新渲染
  • 如何使用useCallback()鉤子來避免在將函數(shù)作為props傳遞給子組件時重新渲染。

希望您覺得這篇關於React記憶化的介紹有用!

關於React記憶化的常見問題解答(FAQ)

(此處與原文類似,只是對語言和表達方式進行了一些調(diào)整。)

以上是如何在REACT中實施回憶以提高性能的詳細內(nèi)容。更多資訊請關注PHP中文網(wǎng)其他相關文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權的內(nèi)容,請聯(lián)絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

為什麼要將標籤放在的底部? 為什麼要將標籤放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

如何在JS中與日期和時間合作? 如何在JS中與日期和時間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時間處理需注意以下幾點:1.創(chuàng)建Date對像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設置時間信息可用get和set方法,注意月份從0開始;3.手動格式化日期需拼接字符串,也可使用第三方庫;4.處理時區(qū)問題建議使用支持時區(qū)的庫,如Luxon。掌握這些要點能有效避免常見錯誤。

什麼是在DOM中冒泡和捕獲的事件? 什麼是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個階段,捕獲是從頂層向下到目標元素,冒泡是從目標元素向上傳播到頂層。 1.事件捕獲通過addEventListener的useCapture參數(shù)設為true實現(xiàn);2.事件冒泡是默認行為,useCapture設為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動態(tài)內(nèi)容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯誤處理。了解這兩個階段有助於精確控制JavaScript響應用戶操作的時機和方式。

如何在node.js中提出HTTP請求? 如何在node.js中提出HTTP請求? Jul 13, 2025 am 02:18 AM

在Node.js中發(fā)起HTTP請求有三種常用方式:使用內(nèi)置模塊、axios和node-fetch。 1.使用內(nèi)置的http/https模塊無需依賴,適合基礎場景,但需手動處理數(shù)據(jù)拼接和錯誤監(jiān)聽,例如用https.get()獲取數(shù)據(jù)或通過.write()發(fā)送POST請求;2.axios是基於Promise的第三方庫,語法簡潔且功能強大,支持async/await、自動JSON轉(zhuǎn)換、攔截器等,推薦用於簡化異步請求操作;3.node-fetch提供類似瀏覽器fetch的風格,基於Promise且語法簡單

JavaScript模塊上的確定JS綜述:ES模塊與COMPORJS JavaScript模塊上的確定JS綜述:ES模塊與COMPORJS Jul 02, 2025 am 01:28 AM

ES模塊和CommonJS的主要區(qū)別在於加載方式和使用場景。 1.CommonJS是同步加載,適用於Node.js服務器端環(huán)境;2.ES模塊是異步加載,適用於瀏覽器等網(wǎng)絡環(huán)境;3.語法上,ES模塊使用import/export,且必須位於頂層作用域,而CommonJS使用require/module.exports,可在運行時動態(tài)調(diào)用;4.CommonJS廣泛用於舊版Node.js及依賴它的庫如Express,ES模塊則適用於現(xiàn)代前端框架和Node.jsv14 ;5.雖然可混合使用,但容易引發(fā)問題

垃圾收集如何在JavaScript中起作用? 垃圾收集如何在JavaScript中起作用? Jul 04, 2025 am 12:42 AM

JavaScript的垃圾回收機制通過標記-清除算法自動管理內(nèi)存,以減少內(nèi)存洩漏風險。引擎從根對像出發(fā)遍歷並標記活躍對象,未被標記的則被視為垃圾並被清除。例如,當對像不再被引用(如將變量設為null),它將在下一輪迴收中被釋放。常見的內(nèi)存洩漏原因包括:①未清除的定時器或事件監(jiān)聽器;②閉包中對外部變量的引用;③全局變量持續(xù)持有大量數(shù)據(jù)。 V8引擎通過分代回收、增量標記、並行/並發(fā)回收等策略優(yōu)化回收效率,降低主線程阻塞時間。開發(fā)時應避免不必要的全局引用、及時解除對象關聯(lián),以提升性能與穩(wěn)定性。

var vs Let vs const:快速JS綜述解釋器 var vs Let vs const:快速JS綜述解釋器 Jul 02, 2025 am 01:18 AM

var、let和const的區(qū)別在於作用域、提升和重複聲明。 1.var是函數(shù)作用域,存在變量提升,允許重複聲明;2.let是塊級作用域,存在暫時性死區(qū),不允許重複聲明;3.const也是塊級作用域,必須立即賦值,不可重新賦值,但可修改引用類型的內(nèi)部值。優(yōu)先使用const,需改變變量時用let,避免使用var。

為什麼DOM操縱緩慢,如何優(yōu)化? 為什麼DOM操縱緩慢,如何優(yōu)化? Jul 01, 2025 am 01:28 AM

操作DOM變慢的主要原因在於重排重繪成本高和訪問效率低。優(yōu)化方法包括:1.減少訪問次數(shù),緩存讀取值;2.批量處理讀寫操作;3.合併修改,使用文檔片段或隱藏元素;4.避免佈局抖動,集中處理讀寫;5.使用框架或requestAnimationFrame異步更新。

See all articles