主题
React 性能优化
React 大列表为什么需要虚拟化?如何设计虚拟列表?
虚拟列表的核心不是“只渲染一部分”,而是用稳定的可视窗口控制 DOM、测量和状态生命周期。
面试官想考什么
- 为什么 10 万条数据不能全部渲染? 考察 DOM、布局和内存成本。
- 固定高度和动态高度如何处理? 考察实现细节。
- 虚拟化会带来什么副作用? 考察产品和可访问性取舍。
- key 和滚动定位如何设计? 考察状态正确性。
一句话回答
text
虚拟列表只保留可视区域和缓冲区的 DOM,通过滚动位置计算窗口,从而把 DOM、渲染和布局成本从全量数据降到可控范围。面试回答详解
1. 全量列表的成本
大量节点会增加 React 协调、DOM 内存、样式计算、布局、绘制和事件处理成本。分页减少数据量,虚拟化则减少当前 DOM 数量,两者可以组合。
2. 核心流程
text
scrollTop + viewport -> 计算 start/end -> 渲染窗口
-> 设置占位高度 -> 回收/复用行 -> 校正滚动位置- 固定高度:索引和偏移计算简单、性能稳定。
- 动态高度:需要测量、缓存和变化修正,滚动跳动风险更高。
- 缓冲区:减少快速滚动时白屏,但缓冲过大又增加 DOM。
3. 正确性边界
使用稳定业务 id 作为 key;行组件被复用时要正确清理局部状态。搜索定位、复制、浏览器查找、打印、SEO 和屏幕阅读器体验需要单独验证。
4. 工程取舍
短列表不必虚拟化;复杂表格、动态高度、树形数据和可编辑行应优先选用成熟库,减少滚动锚点和测量 bug。
可直接背诵的 30 秒回答
text
虚拟列表通过 viewport、scrollTop 和缓冲区计算当前渲染窗口,只保留少量 DOM,所以能控制 React、布局和绘制成本。固定高度实现简单,动态高度要做测量和滚动校正;同时要考虑稳定 key、行状态复用、搜索定位、无障碍、打印和 SEO。分页和虚拟化解决的是不同层次的问题,可以组合使用。扩展知识
大列表优化组合
text
分页/游标 -> 虚拟化 -> 行级 memo -> 稳定 key
-> 分页缓存 -> 低优先级更新 -> 性能监控面试官追问链
追问一:虚拟列表会不会影响 SEO?
- 考察点:是否考虑业务场景。
- 回答方向:未渲染内容不在 DOM 中,可能影响抓取和完整文本;SEO 页面可采用服务端分页、静态内容或非虚拟化首屏。
追问二:动态高度导致滚动跳动怎么办?
- 考察点:实现细节。
- 回答方向:使用估算高度、ResizeObserver、测量缓存和锚点校正,避免在测量前后改变用户视口位置。
追问三:虚拟列表中输入框内容丢失怎么办?
- 考察点:状态生命周期意识。
- 回答方向:把编辑值放在行外部的稳定数据源,或保证回收策略不会销毁仍需保留的编辑状态。