iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > html >如何利用Memoization提高React性能
  • 844
分享到

如何利用Memoization提高React性能

2024-04-02 19:04:59 844人浏览 泡泡鱼
摘要

本篇内容介绍了“如何利用Memoization提高React性能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所

本篇内容介绍了“如何利用Memoization提高React性能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

如何利用Memoization提高React性能

React 是如何渲染视图的?

在讨论 React 中的 Memoization 细节之前,让我们先来看看 React 是如何使用虚拟 DOM 渲染 UI 的。【相关推荐:Redis视频教程

常规 DOM 基本上包含一组用树的形式保存的节点。DOM 中的每个节点代表一个 UI 元素。每当应用程序中出现状态变更时,该 UI 元素及其所有子元素的相应节点都会在 DOM 树中更新,然后会触发 UI 重绘。

在高效的 DOM 树算法的帮助下,更新节点的速度更快,但重绘的速度很慢,并且当该 DOM 具有大量 UI 元素时,可能会影响性能。因此,在 React 中引入了虚拟 DOM。

这是真实 DOM 的虚拟表示。现在,每当应用程序的状态有任何变化时,React 不会直接更新真正的 DOM,而是创建一个新的虚拟 DOM。然后 React 会将此新的虚拟 DOM 与之前创建的虚拟 DOM 进行比较,找到有差异的地方(译者注:也就是找到需要被更新节点),然后进行重绘。

根据这些差异,虚拟 DOM 能更高效地更新真正的 DOM。这样提高了性能,因为虚拟 DOM 不会简单地更新 UI 元素及其所有子元素,而是有效地仅更新实际 DOM 中必要且最小的更改。

为什么需要 Memoization?

在上一节中,我们看到了 React 如何使用虚拟 DOM 有效地执行 DOM 更新操作来提高性能。在本节中,我们将介绍一个例子,该例子解释了为了进一步提高性能而需要使用 Memoization。

我们将创建一个父类,包含一个按钮,用于递增名为 count 的变量。父组件还调用了子组件,并向其传递参数。我们还在 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>
        <h3>{this.state.count}</h3>
        <Child name={"joe"} />
      </div>
    );
  }
}

export default Parent;

此示例的完整代码可在 CodeSandbox 上查看。

我们将创建一个 Child 类,该类接受父组件传递的参数并将其显示在 UI 中:

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

export default Child;

每当我们点击父组件中的按钮时,count 值都会更改。由于 state 变化了,因此父组件的 render 方法被执行了。

传递给子组件的参数在每次父组件重新渲染时都没有改变,因此子组件不应重新渲染。然而,当我们运行上面的代码并继续递增 count 时,我们得到了以下输出:

Parent render
Child render
Parent render
Child render
Parent render
Child render

你可以在这个 sandbox 中体验上述示例,并查看控制台的输出结果。

从输出中,我们可以看到,当父组件重新渲染时,即使传递给子组件的参数保持不变,子组件也会重新渲染。这将导致子组件的虚拟 DOM 与以前的虚拟 DOM 执行差异检查。由于我们的子组件中没有变更且重新渲染时的所有 props 都没有变,所以真正的 DOM 不会被更新。

真正的 DOM 不会进行不必要地更新对性能确实是有好处,但是我们可以看到,即使子组件中没有实际更改,也会创建新的虚拟 DOM 并执行差异检查。对于小型 React 组件,这种性能消耗可以忽略不计,但对于大型组件,性能影响会很大。为了避免这种重新渲染和虚拟 DOM 的差异检查,我们使用 Memoization。

React 中的 Memoization

在 React 应用的上下文中,Memoization 是一种手段,每当父组件重新渲染时,子组件仅在它所依赖的 props 发生变化时才会重新渲染。如果子组件所依赖的 props 中没有更改,则它不会执行 render 方法,并将返回缓存的结果。由于渲染方法未执行,因此不会有虚拟 DOM 创建和差异检查,从而实现性能的提升。

现在,让我们看看如何在类和函数组件中实现 Memoization,以避免这种不必要的重新渲染。

类组件实现 Memoization

为了在类组件中实现 Memoization,我们将使用 React.PureComponent。React.PureComponent 实现了 shouldComponentUpdate(),它对 stateprops 进行了浅比较,并且仅在 props 或 state 发生更改时才重新渲染 React 组件。

将子组件更改为如下所示的代码:

//Child.js
class Child extends React.PureComponent { // 这里我们把 React.Component 改成了 React.PureComponent
  render() {
    console.log("Child render");
    return (
      <div>
        <h3>{this.props.name}</h3>
      </div>
    );
  }
}

export default Child;

此示例的完整代码显示在这个 sandbox 中。

父组件保持不变。现在,当我们在父组件中增加 count 时,控制台中的输出如下所示:

Parent render
Child render
Parent render
Parent render

对于首次渲染,它同时调用父组件和子组件的 render 方法。

对于每次增加 count 后的重新渲染,仅调用父组件的 render 函数。子组件不会重新渲染。

函数组件实现 Memoization

为了在函数组件中实现 Memoization,我们将使用 React.memo()。React.memo() 是一个高阶组件(HOC),它执行与 PureComponent 类似的工作,来避免不必要的重新渲染。

以下是函数组件的代码:

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

export default React.memo(Child); // 这里我们给子组件添加 HOC 实现 Memoization

同时还将父组件转换为了函数组件,如下所示:

//Parent.js
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>
      <h3>{count}</h3>
      <Child name={"joe"} />
    </div>
  );
}

此示例的完整代码可以在这个 sandbox 中看到。

现在,当我们递增父组件中的 count 时,以下内容将输出到控制台:

Parent render
Child render
Parent render
Parent render
Parent render

React.memo() 存在的问题

在上面的示例中,我们看到,当我们对子组件使用 React.memo() HOC 时,子组件没有重新渲染,即使父组件重新渲染了。

但是,需要注意的一个小问题是,如果我们将函数作为参数传递给子组件,即使在使用 React.memo() 之后,子组件也会重新渲染。让我们看一个这样的例子。

我们将更改父组件,如下所示。在这里,我们添加了一个处理函数,并作为参数传递给子组件:

//Parent.js
export default function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  };

  const handler = () => {
    console.log("handler");    // 这里的 handler 函数将会被传递给子组件
  };

  console.log("Parent render");
  return (
    <div className="App">
      <button onClick={handleClick}>Increment</button>
      <h3>{count}</h3>
      <Child name={"joe"} childFunc={handler} />
    </div>
  );
}

子组件代码将保持原样。我们不会在子组件中使用父组件传递来的函数:

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

export default React.memo(Child);

现在,当我们递增父组件中的 count 时,它会重新渲染并同时重新渲染子组件,即使传递的参数中没有更改。

那么,是什么原因导致子组件重新渲染的呢?答案是,每次父组件重新渲染时,都会创建一个新的 handler 函数并将其传递给子组件。现在,由于每次重新渲染时都会重新创建 handle 函数,因此子组件在对 props 进行浅比较时会发现 handler 引用已更改,并重新渲染子组件。

接下来,我们将介绍如何解决此问题。

通过 useCallback() 来避免更多的重复渲染

导致子组件重新渲染的主要问题是重新创建了 handler 函数,这更改了传递给子组件的引用。因此,我们需要有一种方法来避免这种重复创建。如果未重新创建 handler 函数,则对 handler 函数的引用不会更改,因此子组件不会重新渲染。

为了避免每次渲染父组件时都重新创建函数,我们将使用一个名为 useCallback() 的 React Hook。Hooks 是在 React 16 中引入的。要了解有关 Hooks 的更多信息,你可以查看 React 的官方 hooks 文档,或者查看 `React Hooks: How to Get Started & Build Your Own"。

useCallback() 钩子传入两个参数:回调函数和依赖项列表。

以下是 useCallback() 示例:

const handleClick = useCallback(() => {
  //Do something
}, [x,y]);

在这里,useCallback() 被添加到 handleClick() 函数中。第二个参数 [x, y] 可以是空数组、单个依赖项或依赖项列表。每当第二个参数中提到的任何依赖项发生更改时,才会重新创建 handleClick() 函数。

如果 useCallback() 中提到的依赖项没有更改,则返回作为第一个参数提及的回调函数的 Memoization 版本。我们将更改父组件,以便对传递给子组件的处理程序使用 useCallback() 钩子:

//Parent.js
export default function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  };

  const handler = useCallback(() => { // 给 handler 函数使用 useCallback()
    console.log("handler");
  }, []);

  console.log("Parent render");
  return (
    <div className="App">
      <button onClick={handleClick}>Increment</button>
      <h3>{count}</h3>
      <Child name={"joe"} childFunc={handler} />
    </div>
  );
}

子组件代码将保持原样。

此示例的完整代码这个 sandbox 中。

当我们在上述代码的父组件中增加 count 时,我们可以看到以下输出:

Parent render
Child render
Parent render
Parent render
Parent render

由于我们对父组件中的 handler 使用了 useCallback() 钩子,因此每次父组件重新渲染时,都不会重新创建 handler 函数,并且会将 handler 的 Memoization 版本传递到子组件。子组件将进行浅比较,并注意到 handler 函数的引用没有更改,因此它不会调用 render 方法。

值得注意的事

Memoization 是一种很好的手段,可以避免在组件的 state 或 props 没有改变时对组件进行不必要的重新渲染,从而提高 React 应用的性能。你可能会考虑为所有组件添加 Memoization,但这并不一定是构建高性能 React 组件的方法。只有在组件出现以下情况时,才应使用 Memoization:

  • 固定的输入有固定的输出时

  • 具有较多 UI 元素,虚拟 DOM 检查将影响性能

  • 多次传递相同的参数

“如何利用Memoization提高React性能”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 如何利用Memoization提高React性能

本文链接: https://www.lsjlt.com/news/97157.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何利用Memoization提高React性能
    本篇内容介绍了“如何利用Memoization提高React性能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2024-04-02
  • 如何提高React界面性能
    这篇文章主要介绍了如何提高React界面性能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。总的说来,React是通过维护视图中的内存(in-memory)模型来运作的。这通常...
    99+
    2023-06-15
  • 如何利用NumPy提高ASP的性能?
    NumPy是Python科学计算中最重要的库之一,它提供了高效的多维数组操作功能,可以大大提高Python程序的性能。在ASP(Active Server Pages)开发中,使用NumPy可以极大地提高程序的运行效率和性能。本文将介绍如何...
    99+
    2023-09-22
    响应 numpy unix
  • ASP如何利用实时日志提高性能?
    ASP是一种基于服务器的Web开发技术,可以在服务器端执行动态脚本并生成动态Web页面。随着Web应用程序规模的增长,ASP应用程序的性能问题也越来越受到关注。其中一个重要的性能问题是日志记录,因为日志记录会占用服务器资源并影响性能。在本...
    99+
    2023-07-21
    响应 实时 日志
  • 如何利用 PHP 函数提高网站性能?
    通过利用 php 函数,您可以优化网站性能,做法包括:启用输出缓冲区以减少网络请求。使用缓存机制提高数据的快速检索能力。减少数据库调用以避免不必要的数据库操作。优化图像大小以减轻响应负载...
    99+
    2024-04-23
    php 提高网站性能
  • 如何利用算法提高 Laravel 应用的性能?
    Laravel 是一款流行的 PHP Web 应用程序框架,它提供了许多方便的功能和工具,使得开发 Web 应用程序变得更加容易和快速。然而,当您的应用程序增长时,它可能会遇到性能瓶颈,导致应用程序变慢或崩溃。在这篇文章中,我们将探讨如何使...
    99+
    2023-08-12
    编程算法 load laravel
  • ASP网站如何利用并发来提高性能?
    随着互联网的不断发展,越来越多的企业和个人开始使用ASP网站来展示自己的业务和产品。然而,在用户量增加的情况下,ASP网站的性能往往会受到影响,导致网站响应缓慢、访问速度变慢等问题。而并发技术可以帮助ASP网站提高性能,使其更好地服务于用...
    99+
    2023-09-26
    并发 关键字 索引
  • 如何利用 PHP 函数库提高代码性能?
    是的,php 函数库可显著提升代码性能。常用函数有:array_map():应用回调函数至数组元素。in_array():检查数组中特定元素是否存在,效率优于循环。preg_match(...
    99+
    2024-04-26
    php 函数库
  • Javascript之怎么提高React性能
    本篇内容主要讲解“Javascript之怎么提高React性能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Javascript之怎么提高React性能”吧!1.解决重复渲染问题我们大多数人都知...
    99+
    2023-07-05
  • 如何利用编程算法提高 ASP 的性能?
    ASP(Active Server Pages)是一种用于开发动态Web应用程序的服务器端技术,它使用VBScript或JavaScript作为脚本语言,支持各种数据库。ASP的性能对于Web应用程序的响应速度和用户体验至关重要,因此优化A...
    99+
    2023-11-12
    并发 数据类型 编程算法
  • 如何利用PHP开发缓存提高网站性能
    随着互联网技术的不断发展,各种网站的数量也在不断增加,网络流量也越来越大。对于开发者来说,如何提高网站的性能成为了一个重要的问题。其中,利用缓存技术可以有效地提高网站的性能,减轻服务器的压力,提高网站的访问速度。PHP作为一种常用的Web编...
    99+
    2023-11-07
    缓存 PHP 网站性能
  • PHP开发中如何利用Memcache提高程序性能?
    PHP开发中如何利用Memcache提高程序性能?Memcache是一个高性能的内存对象缓存系统,常用于缓存常用数据、页面片段、数据库查询结果等,以减小数据库负载,提高程序的性能。下面将介绍如何在PHP开发中利用Memcache提高程序性能...
    99+
    2023-11-07
    内存管理 PHP性能优化 Memcache缓存
  • 如何利用PHP-FPM优化提高LimeSurvey应用的性能
    一、背景介绍LimeSurvey是一款开源的在线调查软件,它提供了丰富的功能和灵活的配置选项,使得用户可以轻松创建和管理各种类型的调查。然而,随着调查量的增加和用户数量的上升,LimeSurvey应用的性能可能会受到影响。为了解决这个问题,...
    99+
    2023-10-21
    优化 php-fpm 性能提升
  • 如何利用PHP-FPM优化提高Phalcon应用的性能
    导语:Phalcon是一个高性能的PHP框架,结合PHP-FPM可以进一步提高应用的性能。本文将介绍如何利用PHP-FPM优化Phalcon应用的性能,并提供具体的代码示例。一、什么是PHP-FPMPHP-FPM(PHP FastCGI P...
    99+
    2023-10-21
    优化 php-fpm Phalcon 关键词:
  • 如何利用缓存提高ASP应用程序的性能?
    ASP应用程序的性能对于网站的用户体验至关重要。如果您的网站响应速度很慢,那么访问者可能会失去耐心并转向其他网站。因此,优化ASP应用程序的性能至关重要。本文将介绍如何使用缓存来提高ASP应用程序的性能。 一、什么是缓存? 缓存是一种将数据...
    99+
    2023-07-27
    缓存 shell 异步编程
  • 如何利用PHP-FPM优化提高XenForo应用的性能
    引言:XenForo是一款功能强大的社交论坛软件,但随着网站用户量和访问量的增加,性能优化变得至关重要。在优化XenForo应用的过程中,PHP-FPM(FastCGI Process Manager)是一个强大而又灵活的工具。本文将介绍如...
    99+
    2023-10-21
    性能 优化 php-fpm
  • 如何利用PHP-FPM优化提高CodeIgniter应用的性能
    引言:在开发Web应用时,性能是一个非常重要的考量因素。在CodeIgniter框架下,通过合理的配置和优化,可以显著提升应用的性能。本文将介绍如何利用PHP-FPM来优化CodeIgniter应用的性能,并提供具体的代码示例。一、PHP-...
    99+
    2023-10-21
    优化 php-fpm CodeIgniter
  • 如何利用PHP-FPM优化提高Laravel应用的性能
    概述:Laravel是一种流行的PHP框架,采用了现代化的设计理念和优雅的语法,使得开发者能够高效地构建Web应用程序。然而,在处理大量并发请求时,性能问题可能会出现。本文将介绍如何利用PHP-FPM来优化和提高Laravel应用的性能。一...
    99+
    2023-10-21
    优化 php-fpm 性能提升 关键词:
  • Javascript之提高React性能的技巧
    目录1.解决重复渲染问题2.通过拆分组件减少重新渲染3.什么是实例重创建,如何避免?4.不要偷懒懒加载5.何时使用 React 片段?6.避免在列出的元素中使用索引作为键7.避免Sp...
    99+
    2023-05-15
    Javascript提高React性能 提高React性能技巧 React性能技巧
  • 如何利用PATH API提高PHP应用程序的性能?
    PHP是一种非常流行的服务器端编程语言,但是其性能一直是人们关注的焦点。为了提高PHP应用程序的性能,我们可以使用PATH API。PATH API是一个PHP扩展,提供了一些函数和方法,用于优化PHP代码的执行效率。 下面我们将介绍如何使...
    99+
    2023-10-25
    开发技术 path api
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作