以 el-select-v2 为例。十万条数据,页面上始终只有十几个 DOM —— 秘密藏在三个区域的协作里:视口区域、内容区域、占位容器。滚动下面的列表,或按下播放键,观察它们如何一起运动。
一个固定高度、overflow-y:auto 的容器。它做两件事:决定一屏能看到几项;通过滚动事件把 scrollTop(滚了多远)告诉你。它是整个计算的输入。
一个空 div,高度设为 n × itemHeight,里面一个选项都不渲染。唯一任务是"骗"浏览器:让滚动条长度和真实十万行列表一模一样。没有它就没有滚动条、没有惯性滚动。
绝对定位的一层,里面只有"可视项 + 上下缓冲项"这十几个 DOM。用 transform:translateY() 整体下移到视口对应的位置。滚动时换数据、换位移,DOM 数量恒定。
视口触发 scroll,拿到 scrollTop
start = floor(scrollTop / itemH)
end = start + ceil(vpH / itemH),两端加 buffer
只渲染 data.slice(start,end) 这一小段
内容层 translateY(start × itemH)
无论滚到哪,节点数始终是十几条