极致列表渲染性能的关键在于精准控制渲染时机与范围:用稳定 key 和 react.memo 避免无效重渲染;动态高度支持依赖 getitemheight 与 usememo 缓存位置;仅渲染可视区域并用 padding 占位维持滚动体验;结合 usewindowscroll、resizeobserver 和 scrolltoitem 实现高响应式交互。

极致的列表渲染性能不是靠堆砌技术,而是精准控制“什么时候渲染”和“渲染多少”。核心在于避免无效 DOM 操作、减少重绘重排、跳过无变化子组件,并在数据量大时彻底绕过不可见内容的渲染。
用稳定 key + React.memo 切断默认重渲染链
React 默认会在父组件更新时重渲染所有子组件,哪怕 props 完全没变。关键破局点有两个:
- key 必须是数据唯一标识(如 id),绝不能用 index——否则插入/删除会错位,触发大量 DOM 移动和重建
- 列表项组件必须用 React.memo 包裹,它会对 props 做浅比较;只要传入的 item 对象引用不变,组件就不会重新执行 JSX 渲染逻辑
动态高度支持下仍保持滚动流畅
真实业务中列表项高度常不固定(比如文字长度不同、hover 展开详情)。虚拟列表要真正可用,必须能预知每项高度:
- 通过 getItemHeight(item, index) 函数 动态计算每行高度,支持文本截断、图片加载后重测等场景
- 内部用 useMemo 预计算累积位置数组([0, h₀, h₀+h₁, h₀+h₁+h₂, ...]),滚动时仅靠二分查找就能快速定位可视区间起止索引
- 高度变化后需触发重置位置缓存,但不影响当前滚动帧——可结合 useLayoutEffect 或 resize observer 实现平滑过渡
只渲染可视区域,用绝对定位模拟完整滚动容器
虚拟列表不是“懒加载”,而是“按需实例化”:
- 容器设为 relative 定位,内部列表项用 absolute 定位,top 值由预计算的位置数组直接得出
- 用 scrollTop 和 containerHeight 算出 visibleStart / visibleEnd 索引,map 只遍历这个小范围(通常 20–50 项)
- 外层加一层 padding-top / padding-bottom 占位,让滚动条长度反映真实数据总量,用户感知不到“被裁剪”
配合 useWindowScroll + ResizeObserver 应对真实交互
生产环境不能只靠 onScroll:滚动可能来自键盘、API 调用、或容器尺寸变化。
- 监听 window scroll 或容器 scroll,但防抖非节流——滚动中持续采样,停止后 16ms 内同步更新,保障 60fps
- 用 ResizeObserver 监听容器宽高变化,自动重新计算可视行数和位置缓存,适配响应式布局或折叠侧边栏
- 提供 scrollToItem(id) 方法,内部基于累积位置数组快速算出目标 top 值并 smooth scroll,不依赖 ref 查找 DOM











