E4.18.1windowed list rendering设计研究

虚拟滚动只渲染可见区域以维持长列表的性能

别名: 虚拟列表 · 可视区域渲染 · 长列表性能 · virtualized list

概念解释

列表有几千上万行时,把每一行都做成真实节点会拖垮布局和内存。虚拟滚动(windowed rendering)只把视口里那一小段——外加一点缓冲——做成节点,其余行用占位高度撑开滚动条。用户的模型仍是「这是一份完整列表」;实现的模型是「只有窗口里的行存在」。这条讲为什么要这么做、窗口策略保的是什么,不讲查找会怎样、滚动条是否说谎。

机制

每条 DOM 或原生视图都有布局、绘制、事件与可访问树的固定成本。成本随行数线性涨,交互帧率在某一规模后掉到可感知的卡顿,滚动本身变成任务失败。虚拟化把成本钉在窗口大小上:无论数据一万还是十万,同时活着的节点大约是一屏加缓冲。缓冲是为了让即将进入视口的行提前就绪,否则滚一下就要当场创建节点。窗口之外的行在数据层仍在,只是没有视图。对用户,这份完整感靠滚动范围和行号维持;对系统,完整感是假的——辅助技术树、页内查找、打印都会撞上「不在窗口里就不存在」。虚拟化因此是性能与完整性的交换,不是免费的加速。

怎么研究

用同一数据集比较全量渲染与窗口渲染,测量首屏时间、滚动帧率、内存、以及滚动到远端后的交互延迟。自变量:窗口高度、缓冲行数、行高是否可变。因变量:掉帧、卡顿报告、内存峰值。可变行高会迫使窗口估算,应单独看估算误差导致的跳动。不要只用「感觉流畅」——把帧时间分布画出来,长尾卡顿才是虚拟化没覆盖到的创建尖峰。

边界

几十行的列表虚拟化是多余的,窗口开销可能比全量更大。需要同时测量或导出全部行的场景(全选复制、打印)不能只靠窗口,要有一条不经视图的数据通道。服务端分页已经限制了同时存在的数据,再套一层虚拟化要分清两层各保什么。低端设备上窗口还要更小,缓冲过大仍会卡。

怎么落地

  • 以可感知卡顿的数据规模为阈值再启用虚拟化,小列表保持全量。
  • 窗口含一屏加足够缓冲,滚动方向上多备一些。
  • 行高尽量稳定,避免估算高度在滚入时修正造成跳动。
  • 验证:在目标设备上滚完整份长列表,帧时间没有长尾尖峰,内存不随滚过的行数线性涨。

延伸

  • 同组E4.18.2 页面内查找在虚拟滚动下可能失效 · E4.18.3 滚动条位置与实际数据量的映射需保持准确 · E4.18.4 快速滚动时占位内容闪烁会影响可读性
  • 相邻E4.02 列表项 · E5.07 无限滚动
  • 站内检索virtualized list · windowing · recycle views

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/E4.18.1