vue 3 中 usevirtualscroll 组合式函数封装核心是抽离滚动监听、可视范围计算、占位控制、渲染切片流程,只暴露 containerref、visiblestart/end、paddingtop/paddingbottom 及可选 offsety,支持固定/动态高度,精准管理生命周期与防抖。

在 Vue 3 中,把虚拟滚动逻辑封装成组合式函数(Composable),核心是把“滚动监听 → 可视范围计算 → 占位控制 → 渲染切片”这一整套流程抽离为可复用、响应式、无副作用的逻辑单元。它不绑定具体组件结构,只暴露关键状态和行为,让多个列表页一键接入。
封装要点:只管滚动,不管渲染细节
一个健壮的 useVirtualScroll 应该聚焦三件事:容器滚动位置、可视索引范围、占位高度。它不负责生成 DOM,也不处理业务数据格式,只输出:
- containerRef:供父组件绑定滚动容器
- visibleStart / visibleEnd:当前应渲染的数据起止索引
- paddingTop / paddingBottom:用于撑开总高度,维持滚动条比例
- offsetY(可选):配合 transform translateY 实现更流畅偏移
参数设计:兼容固定高与动态高场景
真实项目中,高度可能固定,也可能随内容变化。组合式函数需灵活适配:
- 传入 itemHeight(数字)→ 固定高度模式,直接计算,性能最优
- 传入 itemHeights: Ref
> → 动态高度模式,内部用 ResizeObserver 或首次渲染后测量缓存 - 用 toValue() 统一处理参数来源:支持 ref、computed、普通值,调用方无需关心传的是不是响应式
生命周期与副作用管理
滚动监听必须精准挂载和清理,否则容易内存泄漏或重复绑定:
- 在 onMounted 中检查 containerRef.value 是否存在,再绑定原生 scroll 事件
- 使用 watchEffect 自动追踪 scrollTop、container 尺寸、data 长度等依赖,触发范围重算
- 在 onUnmounted 中移除事件监听器,清空定时器或 ResizeObserver 实例
- 对高频 scroll 事件做防抖(建议用
lodash.throttle或手写轻量节流)
与业务组件协同的典型用法
在组件中使用时,只需两步:绑定容器 + 切片数据 + 设置占位样式:
- 模板里用
<div ref="containerRef"> 挂载滚动容器 <li>渲染时遍历 <code>data.slice(visibleStart, visibleEnd),每项:key="index + visibleStart"保证复用稳定 - 外层加
:style="{ paddingTop: `${paddingTop}px`, paddingBottom: `${paddingBottom}px` }" - 如需 GPU 加速,可用
:style="{ transform: `translateY(${offsetY}px)` }"替代 padding(注意 Safari 兼容性)










