第一性原理
大数据量下的优化,本质上只有三类手段:
- 减少要处理的数据量
- 减少每次更新的计算和渲染成本
- 把不可避免的开销拆散或挪走
第一类:减少“渲染的数据量”
虚拟列表(Virtual List / Windowing)
原理
只渲染“可视区域 + buffer”的 DOM,其余数据不渲染
虚拟列表解决的是 DOM 数量问题,而不是数据量问题
例如:
- 实际数据:10 万条
- 屏幕能显示:20 条
- 实际 DOM:30~40 条 通过 占位高度 + translateY 让滚动条“看起来完整”。
使用场景
- 长列表(聊天记录、评论、日志)
- 表格(上千行)
- 无限滚动
典型库
react-window:轻量,适合固定高度,首选react-virtualized:功能全,支持不定高、表格,体积较大- Ant Design ProTable(内部封装)
列表项高度不固定怎么办?
固定高度好处理——直接用 react-window 的 FixedSizeList,传入 itemSize 即可。
不定高(比如评论里有图片、折叠内容)是难点。常见方案:
- 先用估算高度渲染,挂载后用
ResizeObserver测量真实高度 - 更新高度缓存,触发重新计算偏移量
react-virtualized的CellMeasurer就是这个思路的封装
// react-window VariableSizeList 示例
const getItemSize = (index) => heightCache[index] ?? 80; // 没测到就用估算值
<VariableSizeList
height={600}
itemCount={list.length}
itemSize={getItemSize}
>
{({ index, style }) => (
<div style={style} ref={el => measureHeight(el, index)}>
<Item data={list[index]} />
</div>
)}
</VariableSizeList>核心矛盾:虚拟列表需要提前知道高度来计算偏移,但不定高内容只有渲染后才知道高度。所以不定高虚拟列表本质上是"先猜、后测、再修正"的过程。
分页 / 懒加载(Pagination / Infinite Scroll)
原理
从数据源层面减少一次性加载的数据 不是只减少 DOM,而是:
- 网络传输更少
- 内存占用更低
使用场景
- 搜索结果
- 数据后台
- 内容流
对比虚拟列表
| 分页 | 虚拟列表 | |
|---|---|---|
| 数据是否全量 | ❌ | ✅ |
| DOM 是否全量 | ❌ | ❌ |
| 滚动体验 | 跳页 | 连续 |
第二类:减少“计算和 Diff 成本”
避免不必要的重渲染
原理
让 React 少做 render / diff
render ≠ DOM 更新,但 render 本身也有成本
手段包括:
React.memouseMemouseCallback- 拆分组件
- 合理 key
使用场景
- 列表项复杂
- 父组件频繁更新
- 状态变化局部化
Key 设计优化(列表 Diff)
原理
React 通过 key 建立节点复用关系,不合理的 key 会导致节点重建
错误示例:
{list.map((item, index) => (
<Row key={index} />
))}正确:
<Row key={item.id} />使用场景
- 动态列表
- 可插入、删除、排序
状态下沉 / 状态隔离
原理
把状态放到“最小影响范围”,避免:一个 state 变化 → 整个树 render
使用场景
- 表单
- 表格 cell
- 复杂交互组件
第三类:拆散或转移开销
节流 / 防抖(时间维度优化)
原理
降低事件触发频率
100 次事件 → 10 次处理使用场景
- scroll
- resize
- input
- mousemove
时间分片(Time Slicing / Scheduler)
原理(React Fiber)
把一次长任务拆成多段,在浏览器空闲时执行
React Fiber 的核心价值不是更快,而是 可中断
避免:
- 主线程长时间阻塞
- 页面卡死
使用场景
- 大量计算
- 大规模 Diff
- 低优先级 UI 更新
Web Worker
原理
把纯计算逻辑放到子线程
避免:
- 阻塞 UI
- 掉帧
使用场景
- 数据预处理
- 排序 / 聚合
- 图表计算
- 富文本解析
离屏渲染(Offscreen / Canvas)
原理
不让 DOM 参与高频更新
例如:
- Canvas
- WebGL
- OffscreenCanvas
使用场景
- 动画
- 游戏
- 实时可视化
网络与数据层优化
- 数据裁剪 & 字段精简减少 payload,胜过任何渲染优化
- 服务端聚合能在服务端算的,不在前端算
- SSR / SSG:大数据量场景下,首屏体验优化非常明显