虚拟列表核心是只渲染可视区域并动态管理高度:返回containerRef、visibleRange、visibleItems、totalHeight和measureItem;不定高采用预估+缓存+渐进修正;支持items、estimateSize等轻量配置,不内置业务逻辑。

明确核心目标:只渲染可视区域,动态管理高度
列表虚拟化不是“优化渲染”,而是避免渲染——不把屏幕外的 DOM 创建出来。封装组合式函数时,第一件事是守住这个边界:它只负责计算哪些项该显示、位置在哪、占多高,不接管数据请求、不处理点击逻辑、不控制弹窗。这些属于业务层,应由组件自己调用或通过事件透传。
暴露关键响应式状态和计算属性
一个可复用的 useVirtualList 应返回结构清晰、职责分明的响应式对象:
-
容器引用:
containerRef(供父组件绑定到滚动容器) -
可见项范围:
visibleRange(含startIndex和endIndex,类型为Ref<{ start: number; end: number }>) -
当前渲染项:
visibleItems(带索引与偏移量的数组,如{ item, index, top }) -
总高度:
totalHeight(用于设置列表容器伪滚动高度,保证滚动条比例正确) -
测量工具方法:
measureItem(可选,供外部触发单个项高度重测)
处理不定高:缓存 + 渐进修正
固定高度只需数学计算;不定高必须解决“怎么知道第1000项有多高”。推荐采用三步策略:
- 初始用
estimateSize(预估高度)填充所有项,快速撑开滚动条 - 用
ResizeObserver监听已渲染项的真实尺寸,写入itemHeights: Ref<Record<number, number>>缓存 - 滚动过程中,对新进入可视区的项异步测量,并更新
visibleItems和totalHeight
注意:不要在 computed 中直接调用 getBoundingClientRect,应封装为独立函数,在 watchEffect 或滚动回调中触发,避免响应式依赖污染。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
立即学习“前端免费学习笔记(深入)”;
支持配置与扩展,但保持接口轻量
通过选项对象接收必要参数,避免过度抽象:
-
items: Ref<any[]>—— 必须是响应式数组,确保长度变化能触发重算 -
estimateSize = 48—— 预估行高,影响初始滚动体验 -
buffer = 5—— 额外渲染几行,防止快速滚动时白屏 -
itemKey: string = 'id'—— 指定唯一标识字段,用于缓存键名
不建议内置“节流”“防抖”“加载更多”等逻辑。需要触底加载?在组件里监听 visibleRange.value.end === items.value.length - 1 即可;需要节流滚动?用 useThrottleFn 包一层 handleScroll 更灵活。

















