IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React 性能优化方法useMemo、useCallback -> 正文阅读

[JavaScript知识库]React 性能优化方法useMemo、useCallback

在 React 中,可以使用useMemouseCallback来优化无用渲染的性能问题。本文是自己学习useMemouseCallback的笔记,介绍了它们的使用场景和区

1. useMemo

useMemo用来缓存,保存每次渲染时,不会发生变化的值,减少计算。在一些开销较大值不会变的场景下特别有用。

如下代码所示,定义了两个状态maxcount,在页面上显示当前maxcount的值,并可以点击按钮增加maxcount的值。

定义了一个函数getSum0~max的和,模拟一个开销大的操作,将求和的结果显示在页面上。但是这个求和的操作只依赖于max这个state,与其他值无关。

import { useState } from 'react';

const A = () => {
    const [max, setMax] = useState(100);
    const [count, setCount] = useState(0);

    // 模拟一个开销大的操作
    const getSum = () => {
        console.log('sum被重新计算了');
        let sum = 0;
        for (let i = 0; i <= max; i++) {
            sum += i;
        }
        return sum;
    };

    return (
        <>
            <div>sum:{getSum()}</div>
            <div>
                max:{max} <button onClick={() => setMax(max => max + 1)}>max++</button>
            </div>
            <div>
                count:{count}
                <button onClick={() => setCount(count => count + 1)}>count++</button>
            </div>
        </>
    );
};

export default A;

更改count的值,求和结果sum并不会发生变化,因为求和的操作只依赖于max。若不使用useMemo进行优化,如下图所示,每次更改count的值,都会重新调用一次getSum函数,每次都进行了一次不必要的操作。

可以使用useMemo进行优化,如下代码所示,使用useMemo将函数包裹起来,并在useMemo的第二个参数中,写上max这个依赖项,表示只有当max发生变化时,才重新调用一次getSum函数,否则就使用上一次计算的值

import { useState, useMemo } from 'react';

const A = () => {
    const [max, setMax] = useState(100);
    const [count, setCount] = useState(0);

    // 模拟一个开销大的操作
    const getSum = useMemo(() => {
        console.log('sum被重新计算了');
        let sum = 0;
        for (let i = 0; i <= max; i++) {
            sum += i;
        }
        return sum;
        // 写上依赖项,只有当max发生变化时,才重新计算一次
    }, [max]);

    return (
        <>
            {/* 注意这里的写法 */}
            <div>sum:{getSum}</div>
            <div>
                max:{max} <button onClick={() => setMax(max => max + 1)}>max++</button>
            </div>
            <div>
                count:{count}
                <button onClick={() => setCount(count => count + 1)}>count++</button>
            </div>
        </>
    );
};

export default A;

结果如下图所示,更新count时,并不会重新调用getSum。只有max变化时,才会重新调用getSum,减少了不必要的函数调用和渲染,实现了优化。

注意:

  • useMemo会返回一个值,所以写的是<div>sum:{getSum}</div>而不是<div>sum:{getSum()}</div>,不用自己调用,体会下这里的区别。
  • 传入useMemo的函数会在渲染期间执行,不要在这个函数内部执行与渲染无关的操作。这里只是为了演示,在函数内执行了console.log()
  • 不要忘记写正确的依赖数组。若没有提供依赖数组,useMemo在每次渲染时都会计算新的值。

2. useCallback

useCallback用来缓存函数。通常用于父子组件中,父组件传给子组件一个函数,父组件更新时,传递给子组件的函数也会被重新创建。有时候传递给子组件的函数没必要重新创建,useCallback就可以缓存这个函数,不使这个函数重新被创建

如下代码所示,父组件A内部创建了numcount两个变量,显示在页面上,并可以更新它们的值。创建了一个函数getCount,返回count的值。父组件A向子组件B传递getCount这个函数。

子组件B拿到getCount函数后,调用并将count值显示在页面上。为了演示每次更新时,getCount是否被重新创建,这里使用了Set这个数据结构。在B组件内部将getCount函数的引用存入Set,并显示Set的长度,长度增加则说明getCount函数被重新创建了。

import { useState } from 'react';

const set = new Set();

const A = () => {
    const [num, setNum] = useState(0);
    const [count, setCount] = useState(0);

    const getCount = () => count;

    return (
        <>
            <B getCount={getCount} />
            <div>
                count:{count}
                <button onClick={() => setCount(count => count + 1)}>count++</button>
            </div>
            <div>
                num:{num}
                <button onClick={() => setNum(num => num + 1)}>num++</button>
            </div>
        </>
    );
};

const B = ({ getCount }) => {
    set.add(getCount);
    return (
        <>
            <div>count:{getCount()}</div>
            <div>集合内元素数量:{set.size}</div>
        </>
    );
};

export default A;

结果如下图所示,当num发生变化时,触发父组件A更新,传递给BgetCount函数也被重新创建了。然而getCount函数返回的是countnum发生变化没必要再重新创建一次getCount函数,这造成了性能的浪费。

可以使用useCallback进行性能优化,在创建getCount函数时,使用useCallback包裹,并写上依赖数组[count],表示只有当count变化时,才重新创建一次getCount函数。

import { useState, useCallback } from 'react';

const set = new Set();

const A = () => {
    const [num, setNum] = useState(0);
    const [count, setCount] = useState(0);

    const getCount = useCallback(() => count, [count]);

    return (
        <>
            <B getCount={getCount} />
            <div>
                count:{count}
                <button onClick={() => setCount(count => count + 1)}>count++</button>
            </div>
            <div>
                num:{num}
                <button onClick={() => setNum(num => num + 1)}>num++</button>
            </div>
        </>
    );
};

const B = ({ getCount }) => {
    set.add(getCount);
    return (
        <>
            <div>count:{getCount()}</div>
            <div>集合内元素数量:{set.size}</div>
        </>
    );
};

export default A;

结果如下图所示,count更新时,传递给B组件的getCount函数被重新创建。而num更新时,getCount函数不会被重新创建,这减少了不必要的创建函数开销,实现了优化。

注意:

  • 因为useCallback返回的是一个函数,所以页面上还是要写<div>count:{getCount()}</div>,需要自己调用。体会一下与useMemo的区别。

以上是本人学习所得之拙见,若有不妥,欢迎指出交流!


📘📘欢迎在我的博客上访问:
https://lzxjack.top/

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-16 17:34:47  更:2021-12-16 17:35:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:49:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码