React性能优化的几种方式


前言

React的性能优化大都是交由用户自己来做的,主要体现在减少不必要的渲染,减少不必要的js计算,从而达到性能优化的目的

class组件

  1. PureComponent
    优点:使用方便; 缺点:仅做浅层比较,对于复杂数据结构无法正确识别

  2. shouldComponentUpdate
    这个大家都知道,也是最常用的,前提是不可以用PureComponent
    使用方式:

    (nextProps, nextState) => boolean

    *不建议在 shouldComponentUpdate() 中进行深层比较或使用 JSON.stringify()。这样非常影响效率,且会损害性能;现在React正逐步减少shouldComponentUpdate的重要性

function组件

  1. React.memo
    可以这么理解,React.memo = PureComponent + shouldComponentUpdate;因为它也是做浅层对比,也和should一样有具体的手动控制方法
    不过memo的原理是记忆缓存上一次的渲染结果,而should是直接跳过更新
    使用方法:
const MyComponent = React.memo(function MyComponent(props) {
  /* 使用 props 渲染 */
}, (prevProps, nextProps) => boolean);

*注意后面的回调函数返回结果和should是相反的

  1. React.useMemo(Hooks)
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    React官方定义:

    把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。
    通俗易懂的解释下:该方法接收两个参数,第一个是一个函数,返回一个值,第二个是他的依赖项,只有当依赖项里的值发生变化了,前面那个函数才会重新计算,否则不会重新计算,套用上次缓存下来的值,避免无用的js计算。

特地去搭了个服务演示一下,下面是我的代码:

import React from "react";

function App() {
  const [num, setNum] = React.useState(1);
  const [str, setStr] = React.useState("yeah");
  const value = () => {
    console.log("重新计算了嗷");
    return str + "~~";
  };
  // const memoValue = React.useMemo(value,[str])
  console.log('1')
  return (
    <div>
      <h1>在线调试页面</h1>
      <span>{value()}</span>
      <button onClick={() => setNum(num + 1)}>改变num</button>
      <button onClick={() => setStr(str + '-')}>改变str</button>
    </div>
  );
}

export default App;

首先是没有用memo的情况,value的结果完全是跟着str走的,按理说我们想看到的是点击第一个按钮不触发重新计算,但是它计算了,因为React的机制,页面的state改变了,就会重新渲染,那么return里的代码会重新走一遍;

上图是我分别点击了两个按钮之后触发的console,接下来试试useMemo

import React from "react";

function App() {
  const [num, setNum] = React.useState(1);
  const [str, setStr] = React.useState("yeah");
  const value = () => {
    console.log("重新计算了嗷");
    return str + "~~";
  };
  const memoValue = React.useMemo(value,[str])
  console.log('1')
  return (
    <div>
      <h1>在线调试页面</h1>
      <span>{memoValue}</span>
      <button onClick={() => setNum(num + 1)}>改变num</button>
      <button onClick={() => setStr(str + '-')}>改变str</button>
    </div>
  );
}

export default App;

再次点击两个按钮:

显然,虽然页面重新渲染了,但是value没有重新计算了,是不是很神奇~
例子只是很简单的一个展示,当计算开销大的时候,比如有多次循环或者递归啥的,这性能优化可就明显了

  1. React.useCallback
    const memoizedCallback = useCallback(
      () => {
        doSomething(a, b);
      },
      [a, b],
    );
    和useMemo没什么差别,区别是返回的是一个回调函数,memo返回的是值

目前想到的就是这些,也是比较常用的,后续有其他的想法会继续更新~


文章作者: Li Dong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Li Dong !
评论
  目录