【前端】【业务场景】【面试】在前端项目中,当涉及大量数据渲染时,如何提高渲染性能并避免页面卡顿?
大量数据渲染性能优化:四层进阶法
循序渐进:先限量 → 再懒渲 → 后分批 → 终极后台协作
1 虚拟滚动:一次只保留“看得见”的节点
- 核心思路:固定容器高度,让滚动条滚动 假象 的总长度;可视窗口内仅挂载极少量行元素。
- 工具首选
框架 轻量库 亮点 React react-window
< 5 KB比 react-virtualized
体积更小Vue2/3 vue-virtual-scroll-list
支持动态行高 原生 clusterize.js
零依赖,table 支持好 - 要点:
- 动态行高时记得缓存行高,减少二次回流。
- 滚动事件节流:
requestAnimationFrame
包装onScroll
。
2 懒加载 / 分页:把“总量”切碎
- 前端分页:仅适合一次性拿到全部数据,再切页展示。
- 后端分页(推荐):接口携带
page / pageSize
,滚动触底或按钮翻页。const fetchPage = (page = 1) =>fetch(`/api/users?page=${page}&size=20`).then(r => r.json())
- 无限滚动 UX:触底自动
loadMore
,同时保留“回顶”按钮,防迷失。
3 分批渲染:给主线程透口气
function chunkRender(list, size = 100) {let i = 0const container = document.getElementById('root')function work(deadline) {while (i < list.length && deadline.timeRemaining() > 1) {const el = document.createElement('li')el.textContent = list[i++]container.appendChild(el)}i < list.length && requestIdleCallback(work)}requestIdleCallback(work)
}
- 兼容性兜底:若
requestIdleCallback
不可用,用setTimeout(fn, 0)
+ 任务队列。 - React 18:使用
startTransition
将低优先级批量更新标为可打断。
4 后台协作:把重活丢给 Web Worker 或 WASM
- 场景:数据预计算 / 巨量 JSON 解析 / CSV 转换。
- 做法:
const worker = new Worker('./parser.worker.js') worker.postMessage(bigFile) worker.onmessage = ({data}) => setRows(data) // 主线程仅渲染
- 再提升:OffscreenCanvas 绘图或使用 WASM+SIMD 做排序搜索。
组合策略速查表
数据规模 | 场景示例 | 建议组合 |
---|---|---|
1 k–5 k 行 | 设置页表、评论 | 虚拟滚动 |
5 k–20 k 行 | 聊天记录、日志 | 虚拟滚动 + 懒加载接口 |
20 k+ 行 | 数据分析面板 | 虚拟滚动 + 后端分页 + Web Worker 预处理 |
复杂计算 | 大 CSV → 图表 | Worker/WASM + 分批渲染 |
🚀 记忆口诀
“虚拟滚 → 懒到手 → 闲批渲 → 工人干”
按需叠加这四招,十万级数据依旧顺滑,拒绝卡顿白屏。