前言:为什么需要优化?
React虽然很快,但不当的使用方式会让你的应用变得卡顿。想象一下用户对着转圈圈的页面干瞪眼的样子——这可不是我们想要的体验。
跟着这篇指南,4分钟让你掌握React性能优化的核心技巧!
一、函数组件三叉戟🔱
1. React.memo - 记住组件
const MyComponent = React.memo(({ data }) => {
return <div>{data}</div>
})
就像给组件装了"记忆芯片",只有props真的变了才会重新渲染。
// React.memo通过浅比较,比较props的变化,决定是否重新渲染。
// 只有当 props的引用或者值改变才触发重渲染。
const UserProfile = React.memo(({ user, settings }) => {
return (
<div>
<Avatar url={user.avatar} />
<ThemePicker theme={settings.theme} />
</div>
)
})
在项目中,用到的地方,比如说:
- 纯展示的(头像、卡片等)
- 静态子组件(它的父组件需要频繁更新的)
- 复杂props的组件
2. useMemo - 记住计算结果
const result = useMemo(() => expensiveCalculation(input), [input])
把昂贵的计算结果缓存起来,避免每次渲染都重新计算。
比如说,做大数据量的排序:
// 大数据量排序
const sortedList = useMemo(() => {
return bigData.sort((a, b) => a.value - b.value)
}, [bigData])
// 复杂对象转换
const chartOptions = useMemo(() => ({
title: { text: dataset.name },
series: dataset.points.map(...)
}), [dataset])
务必牢记:
- 计算成本 > 缓存成本,用它。
- 依赖要精准。
- 不要哪里都用,简单计算的就不要用它了。
3. useCallback - 记住函数
const handleClick = useCallback(() => {
doSomething(id)
}, [id])
防止函数被重复创建,特别适合传给子组件的回调函数。
// 父组件
const Parent = () => {
const handleSelect = useCallback((id) => {
setSelectedId(id)
}, [])
return <Child onSelect={handleSelect} />
}
// 子组件 与React.memo配合使用效果最佳
const Child = React.memo(({ onSelect }) => {
return <Button onClick={onSelect} />
})
注意:避免在useCallback内部创建新对象。
这三个就像"性能三剑客",配合使用效果更佳!
二、类组件两大绝招
1. PureComponent
class MyComp extends React.PureComponent {
render() {
return <div>{this.props.data}</div>
}
}
自动帮你做浅比较,相当于自带shouldComponentUpdate。
2. shouldComponentUpdate
shouldComponentUpdate(nextProps) {
return nextProps.id !== this.props.id
}
手动控制更新条件,适合复杂比较场景。
定律:(1)、优先用PureComponent;(2)、可以搭配immutable.js一起用。
三、通用优化技巧
1. 列表渲染要加key
{items.map(item => (
<Item key={item.id} /> // ✅ 用唯一id
// <Item key={index} /> ❌ 别用索引!
))}
长列表优化,可以适当地恰当地用库来做,比如说react-window(推荐),react-virtualized(功能全面)。图片的话,用Intersection Observer做懒加载。数据实在太大,10万以上的话结合一下Web Worker去开一个异步线程去处理吧,不要堵塞住。
2. 懒加载大组件
const HeavyComp = React.lazy(() => import('./HeavyComp'))
function App() {
return (
<Suspense fallback={<Spinner />}>
<HeavyComp />
</Suspense>
)
}
3. 避免不必要的div嵌套
// 🚩 用不到的div就尽量去除,能去除就出去
return (
<div>
<div>
<Child />
</div>
</div>
)
// ✅
return <Child />
四、常见误区
- 过度优化:不是所有组件都需要memo
- 错误使用key:用index当key等于没优化
- 滥用useMemo:简单计算不需要缓存
- 忽略开发工具:React DevTools能帮你找出性能瓶颈
记住:先写功能,再测性能,最后优化!永远不要过早优化,过早优化是万恶之源!
五、性能检测工具
- React DevTools的Profiler
- Chrome的Performance面板
- 安装why-did-you-render:
npm install @welldone-software/why-did-you-render
总结:优化
- 用React.memo包裹纯展示组件
- 复杂计算用useMemo缓存
- 回调函数用useCallback包裹
- 列表必须加稳定的key
- 大组件使用懒加载
- 定期用性能工具检测
优化就像给代码做健身,适当的"锻炼"能让你的应用跑得更快。但记住——过度优化反而会让代码难以维护,要适当,拿捏好度。