• 售前

  • 售后

热门帖子
入门百科

React函数式组件的性能优化思路详解

[复制链接]
康乃馨老太 显示全部楼层 发表于 2021-10-26 13:37:36 |阅读模式 打印 上一主题 下一主题
优化思路

重要优化的方向有2个:
       
  • 淘汰重新 render 的次数。因为在 React 里最重(花时间最长)的一块就是 reconction(简单的可以理解为 diff),如果不 render,就不会 reconction。   
  • 淘汰计算的量。重要是淘汰重复计算,对于函数式组件来说,每次 render 都会重新从头开始实行函数调用。
在利用类组件的时候,利用的 React 优化 API 重要是:shouldComponentUpdate和 PureComponent
那么在函数式组件中,我们怎么做性能优化?重要用到下面几个方法去优化
       
  • React.memo   
  • useCallback   
  • useMemo
React.memo

看个例子:
我们在父组件中放一个按钮用于修改子标题,并引入Child子组件
可以看到,第一次进来子组件打印了console.log('我是子组件')
当点击修改子标题,Child子组件也打印了,造成了不须要的重复渲染次数
  1. //父组件
  2. import {useState} from 'react'
  3. import Child from "./Child";
  4. const Index = ()=>{
  5.     const [subTitle, setSubTitle] = useState('我是子标题')
  6.     const updateSubTitle = ()=>{
  7.       setSubTitle('修改子标题')
  8.     }
  9.     return (
  10.       <div>
  11.         <div>函数式组件性能优化</div>
  12.         <div>{subTitle}</div>
  13.         <button onClick={updateSubTitle}>修改子标题</button>
  14.         <Child/>
  15.       </div>
  16.     );
  17.   }
  18.   
  19.   export default Index;
  20. //子组件Child.js
  21. const Child = ()=>{
  22.     console.log('我是子组件')
  23.     return (
  24.         <div>我是子组件</div>
  25.     )
  26. }
  27. export default Child
复制代码
优化一下,利用React.memo包裹子组件
  1. import React from "react";
  2. const Child = ()=>{
  3.     console.log('我是子组件')
  4.     return (
  5.         <div>我是子组件</div>
  6.     )
  7. }
  8. export default React.memo(Child)
复制代码
再观察一下,发现Child子组件没有重复渲染了
useCallback

这里我们再改造一下,给Child子组件添加一个onclick变乱,然后点击修改子标题按钮,发现我们的Child子组件又重新渲染了,这里重要是因为修改子标题的时候handlerClick函数重新渲染变革,造成子组件重新渲染
  1. // 父组件
  2. const Index = ()=>{
  3.     const [subTitle, setSubTitle] = useState('我是子标题')
  4.     const updateSubTitle = ()=>{
  5.       setSubTitle('修改子标题')
  6.     }
  7.     const handlerClick = ()=>{
  8.       console.log('子组件点击')
  9.     }
  10.     return (
  11.       <div>
  12.         <div>函数式组件性能优化</div>
  13.         <div>{subTitle}</div>
  14.         <button onClick={updateSubTitle}>修改子标题</button>
  15.         <Child onClick={handlerClick}/>
  16.       </div>
  17.     );
  18.   }
  19. // Child子组件
  20. const Child = (props)=>{
  21.     console.log('我是子组件')
  22.     return (
  23.         <div>
  24.             <div>我是子组件</div>
  25.             <button onClick={props.onClick}>子组件按钮</button>
  26.         </div>
  27.     )
  28. }
  29. export default React.memo(Child)
复制代码
优化一下,利用useCallback包裹处置惩罚子组件的handlerClick函数,再次点击updateSubTitle修改子标题,发现Child子组件没有重新再渲染
  1. // 父组件
  2. const Index = ()=>{
  3.     const [subTitle, setSubTitle] = useState('我是子标题')
  4.     const updateSubTitle = ()=>{
  5.       setSubTitle('修改子标题')
  6.     }
  7.     const handlerClick = useCallback(()=>{
  8.       console.log('子组件点击')
  9.     },[])
  10.     return (
  11.       <div>
  12.         <div>函数式组件性能优化</div>
  13.         <div>{subTitle}</div>
  14.         <button onClick={updateSubTitle}>修改子标题</button>
  15.         <Child onClick={handlerClick}/>
  16.       </div>
  17.     );
  18.   }
  19.   
  20.   export default Index;
复制代码
这里关于useCallback的用法
  1. const callback = () => {
  2.   doSomething(a, b);
  3. }
  4. const memoizedCallback = useCallback(callback, [a, b])
复制代码
把函数以及依赖项作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,这个 memoizedCallback 只有在依赖项有变革的时候才会更新。
useMemo

useMemo用于计算结果缓存
我们先看个例子,在之前底子上添加一个calcCount计算函数,然后点击updateSubTitle更新子标题,发现calcCount重新计算了,也就是每次渲染都会造成重复计算,如果是计算量比力大的情况下,会极大的影响性能
  1. // 父组件
  2. const Index = ()=>{
  3.     const [subTitle, setSubTitle] = useState('我是子标题')
  4.     const updateSubTitle = ()=>{
  5.       setSubTitle('修改子标题')
  6.     }
  7.     const handlerClick = useCallback(()=>{
  8.       console.log('子组件点击')
  9.     },[])
  10.     const calcCount = ()=>{
  11.       
  12.       let totalCount = 0
  13.       for(let i=0;i<10000;i++){
  14.         totalCount+=i
  15.       }
  16.       console.log('totalCount',totalCount)
  17.       return totalCount
  18.     }
  19.     const count = calcCount()
  20.     return (
  21.       <div>
  22.         <div>函数式组件性能优化</div>
  23.         <div>{subTitle}</div>
  24.         <button onClick={updateSubTitle}>修改子标题</button>
  25.         <div>count:{count}</div>
  26.         <Child onClick={handlerClick}/>
  27.       </div>
  28.     );
  29.   }
复制代码
优化一下,利用useMemo缓存计算结果,我们再次点击updateSubTitle修改子标题按钮,可以发现calcCount函数不再重复计算
  1. const calcCount = ()=>{
  2.       
  3.       let totalCount = 0
  4.       for(let i=0;i<10000;i++){
  5.         totalCount+=i
  6.       }
  7.       console.log('totalCount',totalCount)
  8.       return totalCount
  9.     }
  10.     const count = useMemo(calcCount,[])
复制代码
最后,须要留意的是不能盲目的利用useMemo,要根据详细的场景,比如对于一个数据计算量比力大,那么利用是比力实用的,而对于平凡的一些值得计算,可以不利用,因为自己useMemo也是会斲丧一些性能,盲目利用反而会拔苗助长
参考阅读

https://mp.weixin.qq.com/s/YGvmSrr-yhPUNHbwlLSFsA
http://www.ptbird.cn/react-hook-useMemo-purerender.html
到此这篇关于React函数式组件的性能优化的文章就先容到这了,更多干系React性能优化内容请搜刮脚本之家以前的文章或继续欣赏下面的干系文章希望各人以后多多支持脚本之家!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作