第一性原理
大数据量下的优化,本质上只有三类手段:
- 减少要处理的数据量
- 减少每次更新的计算和渲染成本
- 把不可避免的开销拆散或挪走
第一类:减少“渲染的数据量”
虚拟列表(Virtual List / Windowing)
原理
只渲染“可视区域 + buffer”的 DOM,其余数据不渲染
虚拟列表解决的是 DOM 数量问题,而不是数据量问题
例如:
- 实际数据:10 万条
- 屏幕能显示:20 条
- 实际 DOM:30~40 条 通过 占位高度 + translateY 让滚动条“看起来完整”。
使用场景
- 长列表(聊天记录、评论、日志)
- 表格(上千行)
- 无限滚动
典型库
- react-window
- react-virtualized
- Ant Design ProTable(内部)
分页 / 懒加载(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:大数据量场景下,首屏体验优化非常明显