Vue插槽通过作用域插槽将渲染权交给父组件,子组件专注可视范围计算与位置控制;传递item、index、top等参数,配合transform定位、占位元素撑高及滚动监听,实现高性能虚拟滚动。

Vue 插槽本身不直接实现虚拟滚动,但它能和虚拟滚动逻辑深度协同——关键在于:用作用域插槽把“渲染权”交给父组件,而子组件专注做“范围计算+位置控制”。这样既保持结构解耦,又确保高性能。
作用域插槽传递可视项数据
子组件内部维护 visibleItems(仅当前可视区域的数据片段),再通过作用域插槽把每项的 item、index、甚至 top 位置或 height 一并传出:
- 模板中不写具体 DOM 结构,只留
<slot :item="item" :index="index" :top="itemTop"></slot> - 父组件用
v-slot="{ item, index, top }"接收,并自由决定怎么渲染:带图标、骨架屏、懒加载图、条件样式等 - 避免在插槽里写
v-for,因为循环已在子组件内完成,插槽只负责单条渲染
配合 transform 定位实现“伪绝对布局”
子组件需控制每个插槽内容的视觉位置,而不是依赖文档流排列:
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 用
transform: translateY(top + 'px')把每个插槽包裹的 DOM 元素精准摆到对应位置 - 所有插槽项统一放在一个
position: relative或无定位的容器里,靠 transform 移动,不触发重排 - 若需支持动态高度,可传入
height并结合ResizeObserver缓存实际尺寸,再动态更新top和总占位高度
占位元素撑开滚动空间
滚动条要正常显示,必须让容器感知“完整列表高度”:
立即学习“前端免费学习笔记(深入)”;
- 在插槽外层加一个
<div class="phantom" :style="{ height: totalHeight + 'px' }"></div> -
totalHeight由子组件根据数据长度 × 预估高度(或缓存高度总和)计算得出 - 这个占位元素不参与交互,也不进 tab 顺序,纯属为滚动机制服务
滚动监听与可视范围更新
子组件负责监听滚动并实时更新可见区间,父组件无需关心细节:
- 监听容器
@scroll.passive,读取scrollTop - 结合
itemHeight(固定高)或heightCache(动态高),算出startIndex和endIndex - 通过
computed或useVirtualListHook 自动更新visibleItems,触发插槽重新渲染 - 推荐用
IntersectionObserver替代 scroll 监听页脚,实现无限加载更稳定

















