跳到正文

虚拟滚动

Virtual Scrolling

列表只渲染看得见的那几行,一万条也能滚得顺。

  • 又叫:
  • 虚拟列表
  • 长列表优化
  • 窗口化渲染
  • virtual list
  • windowing
  • virtualized list
展厅
布局与结构
形态
自带滚动
播放
手动触发
关键词
需要 JS / 浏览器 API / 合成层动画 / 会引发重排 / 主线程每帧 / 可以直接用
↕ 自己动手试试
L-07形态 自带滚动播放 手动触发Virtual Scrolling

参数工作台

复制给 AI

随参数实时更新

做一个虚拟滚动列表(virtual scrolling):总条数 10000,每行固定 44px,容器内放一个 10000 × 44px 的占位撑出滚动条,只渲染可视区行数加上前后各 4 行,用 transform: translateY 把渲染块定位到对应位置。scroll 里用 requestAnimationFrame 节流,只在可视区间变化时才更新;行用 aria-setsize / aria-posinset 报出总数与序号。

什么时候用

  • 几百到几万行的列表、日志、表格,全渲染会让页面卡死
  • 聊天记录、时间线这类只往两头长的数据
  • 可视区高度固定的面板里展示很长的候选列表

适用场景:列表 / 滚动 / 页面

推荐取值

行高
固定 40–64px 最省事
缓冲行数
前后各 3–6 行
滚动处理
requestAnimationFrame 节流,或只监听可视区间变化
占位高度
总行数 × 行高
无障碍
aria-setsize / aria-posinset 报出总数与序号

别搞混

  • 和「无限滚动」的区别

    无限滚动管「什么时候再取一批数据」,虚拟滚动管「一屏只渲染几行」;一个解决数据量,一个解决 DOM 量,经常一起用。

  • 和「分页」的区别

    分页把数据切成页、用户翻页;虚拟滚动数据一次拿全,只是把可视区外的行不渲染,滚动条仍然是连续的一整条。

容易踩的坑

  • 行高固定才好算区间;高度不定就得逐行测量并缓存,成本随之上升
  • 滚动容器要有撑满总高度的占位(spacer 或 padding),否则滚动条与位置全不对
  • scroll 事件里直接 setState 会掉帧,用 requestAnimationFrame 节流,或者只在可视区间变化时才更新
  • 可视区外多渲染几行做缓冲(overscan),否则快速滚动会看到空白
  • 复用 DOM 时要清掉上一行的动画与展开状态,别让第 500 行的状态串到第 12 行
  • 读屏软件看不到没渲染的行:用 aria-setsize / aria-posinset 报出总数与位置,或提供「跳到第 N 条」

无障碍降级

虚拟滚动本身不播动画;只有「滚到第 N 条」这类平滑滚动在 prefers-reduced-motion 下要改成瞬间定位。

关键词

  • virtual scrolling
  • windowing
  • virtual list
  • overscan
  • item height
  • scrollTop
  • transform: translateY
  • aria-setsize

参考

相关展品