React高级进阶教程--如何打造高性能的应用

304 阅读3分钟

引言

普适的性能优化手段对于 React 同样奏效

以 React 组件的形式来组织逻辑

组件允许我们将 UI 拆分为独立可复用的代码片段

并对每个片段进行独立构思

  • 使用 shouldComponentUpdate 规避冗余的更新逻辑
  • PureComponent + Immutable.js
  • React.memo 与 useMemo

朴素思路:善用 shouldComponentUpdate

是一个 React 类组件的一个生命周期

shouldComponentUpdate(nextProps, nextState)

React 组件会根据 shouldComponentUpdate 的返回值

来决定是否执行该方法之后的生命周期

进而决定是否对组件进行 re-render(重渲染)

默认值为 true,也就是说“无条件 re-render”

通过一个 Demo,来感受一个如何解决问题!

这个 Demo 演示的就是在父组件被渲染时,子组件也都会被 re-render。

如果在 shouldComponent 函数中增加一下对比,那么就可以避免掉这次 re-render。

进阶玩法:PureComponent + Immutable.js

PureComponent: 提前帮你安排好更新判定逻辑

shouldComponentUpdate 虽然一定程度上帮助我们解决了这个性能问题

但在写了不计其数个 shouldComponentUpdate 逻辑之后,难免会怀疑人生

React 15.3 新增了一个叫 PureComponent 的类

PureComponent 将会在 shouldComponentUpdate 中

对组件更新前后的 props 和 state 进行浅比较

并根据浅比较的结果,决定是否需要继续更新流程

浅比较:值类型比较值是否相等,引用类型比较其引用是否相等

数据类型为引用类型

  1. 若数据内容没变,但是引用变了

那么浅比较仍然会认为“数据发生了变化”,进而触发一次不必要的更新导致过度渲染。

  1. 若数据内容变了,但是引用没变

那么浅比较则会认为“数据没有发生变化”,进而阻断一次更新,导致不渲染

Immutable: “不可变值”让“变化”无处遁形

PureComponent 浅比较带来的问题

本质上是对“变化”的判断不够精准导致的

Immutable.js 是对“不可变值”这一思想的实践

  • 持久性数据 指的是这个数据只要被创建出来了,就不能被更改

我们当前数据的任何修改动作,都会导致一个新的对象返回

以上都是类组件的优化思路

函数组件的性能优化:React.memo 和 useMemo

在函数组件中,有没有什么通用的手段可以阻止 “过度 re-render” 的发生呢?

“函数版” 的 shouldComponentUpdate/PureComponent -- React.memo

React.memo:“函数” shouldComponentUpdate/PureComponent

function Demo(props) (xxx)

function areEqual(prevProps, nextProps) { }

export default React.memo(FunctionDemo, areEqual) 

React.memo 控制是否需要渲染一个组件

useMemo 控制的则是是否需要重要执行某一段逻辑

useMemo: 更加“精细”的 memo

这个函数的作用主要就是缓存一些昂贵的计算,如果依赖没变的话,使用上次计算的结果

const renderCount = useMemo(() => (<Text>{count}</Text>), [count])
const renderText = useMemo(() => (<Text>{text}</Text>), [text])
const Comp = (props) => {
    return (
        { renderCount() }
        { renderText() }
    )
}

可以在页面内更加精细的重绘

总结

学习了 React 组件性能优化中最重要的 3 个思路

这3个思路不仅可以作为大家日常实战的知识储备

更能够帮助你在面试场景下做到言之有物

若你能把握好本讲的内容,选择其中一个或多个方向深入探究,相信你已经超越了大部分的同行