Array.from 适合生成虚拟滚动所需的占位数据,创建稠密数组并支持映射函数一步生成带索引的轻量对象,配合可视区域计算与按需渲染实现高效列表。

Array.from 本身不实现虚拟滚动,但它非常适合生成“占位数据”——即结构统一、长度可控、带索引信息的轻量数组,为虚拟滚动提供基础数据支撑。关键在于:用它创建一个“逻辑长度足够大”的数组(比如 10000 条),但每项只是含 index 或 id 的空壳对象,不存真实内容,也不触发渲染。
为什么用 Array.from 而不是 new Array(n)
new Array(10000) 创建的是稀疏数组(empty slots),无法直接遍历或 map;而 Array.from({ length: 10000 }) 会生成一个真正拥有 10000 个 undefined 元素的稠密数组,支持索引访问和映射转换。
更进一步,它支持第二个参数作为映射函数,一步生成带序号的对象:
const placeholderData = Array.from({ length: 10000 }, (_, i) => ({
id: `item-${i}`,
index: i,
height: 0, // 后续可被动态测量填充
rendered: false // 标记是否已真实渲染
}));
结合虚拟滚动容器计算可视区域
假设你有一个高度固定(如 600px)的滚动容器,每条真实内容平均高 80px,则最多显示约 8 条。你只需根据 scrollTop 和容器高度,算出当前应渲染的起始索引 startIndex 和结束索引 endIndex:
- 监听容器的
scroll事件,读取scrollTop - 用
Math.floor(scrollTop / 80)得到首条可见项的逻辑索引 - 取前后各 2–3 条作缓冲区(例如
startIndex - 2到endIndex + 2),避免滚动时白屏 - 用
slice(start, end)从 placeholderData 中快速截取待渲染片段
按需注入真实数据(懒加载/异步填充)
placeholder 对象里的 rendered: false 是关键开关。当某项进入可视区且尚未渲染时:
- 触发一次数据获取(如从 Map 缓存查、或发 API 请求)
- 将真实字段(
title、content、imgUrl等)合并进该 placeholder 对象 - 设
rendered = true,触发局部更新(如 React 中用useState更新该项) - 后续滚动再遇到它,直接跳过加载,复用已有数据
这样既保持了总列表长度不变(维持滚动高度),又避免了一次性加载全部数据。
注意事项与优化点
- 占位数组只需生成一次,全局复用,不要每次 scroll 都重造
- 真实 DOM 元素数量严格控制在可视区+缓冲区范围内,用
key={item.id}保证复用 - 滚动高度(
scrollHeight)由totalLength * averageItemHeight动态维护,即使部分项高度不同,也可用ResizeObserver回填修正 - 若需支持动态增删,建议用
Map替代纯数组管理 placeholder,以id为键做 O(1) 查找和更新


















