Vue 3 实现高性能虚拟列表:Spacer 占位 vs Absolute 定位,哪种更优?

📖 正文

在前端开发中,大数据量列表渲染 一直是性能挑战。假设我们有一个 API 返回 1 万条数据 ,如果直接渲染到页面,必然会导致严重卡顿甚至浏览器崩溃。

解决方案就是 ------ 虚拟列表 (Virtual List) 。

虚拟列表的核心思想是:只渲染当前视口范围内的元素 ,通过计算位置来"假装"完整渲染。

常见实现方式主要有两种:

  1. Spacer 占位法
  2. Absolute 定位法

本文将对比这两种实现,并给出适用场景。


🔹 1. Spacer 占位法实现

思路:用 上空白块 + 下空白块 撑出容器总高度,视口中只渲染真实元素。

xml 复制代码
<div ref="root" @scroll="onScroll"
     :style="{ overflowY: 'auto', height: containerHeight + 'px' }">
  <!-- 上占位 -->
  <div :style="{ height: topSpacer + 'px' }"></div>

  <!-- 可见元素 -->
  <div v-for="item in visibleItems" :key="item.id" class="virtual-item">
    {{ item.text }}
  </div>

  <!-- 下占位 -->
  <div :style="{ height: bottomSpacer + 'px' }"></div>
</div>

👉 优点:

  • 实现简单直观
  • 支持动态高度(只要调整 spacer 值即可)

👉 缺点:

  • 多余的 DOM(两个 spacer)
  • 每次滚动都要更新 topSpacer 和 bottomSpacer,涉及 回流 (Reflow)

🔹 2. Absolute 定位法实现

思路:先撑出一个 固定高度的容器 ,每个 item 通过 absolute + top 定位。

xml 复制代码
<div ref="root" @scroll="onScroll"
     :style="{ overflowY: 'auto', height: containerHeight + 'px', position: 'relative' }">
  
  <!-- 总高度容器 -->
  <div :style="{ height: totalHeight + 'px', position: 'relative' }">
    <div v-for="(item, idx) in visibleItems"
         :key="item.id"
         class="virtual-item"
         :style="{ position: 'absolute', top: (startIndex + idx) * itemHeight + 'px' }">
      {{ item.text }}
    </div>
  </div>
</div>

👉 优点:

  • DOM 结构更简洁(没有 spacer)
  • 绝对定位减少回流,性能更好
  • 更适合大数据场景(5w+ 条时依然稳定)

👉 缺点:

  • 对自适应高度支持不友好(必须固定高度)
  • position: sticky 等布局特性会失效

🔹 3. 性能对比

对比维度 Spacer 占位法 Absolute 定位法
DOM 结构 多 2 个占位元素 更简洁
回流影响 spacer 高度频繁变化,可能触发回流 元素绝对定位,回流更少
动态高度 支持,容易实现 支持困难,需要累积高度映射
大数据量 (10w+) 可能浮点误差 更稳,FPS 更高
布局特性 流式布局更自然 绝对定位可能受限

🔹 4. 实践建议

  • 固定高度 item → 推荐 Absolute 定位法
    简洁高效,减少 DOM & 回流开销。
  • 动态高度 item → 推荐 Spacer 占位法
    更容易适配复杂布局。
  • 超大数据量 (5w+ 条) → Absolute 更稳

如果你要做一个通用组件,可以支持 两种实现方式切换:

  • 默认使用 Absolute 定位法
  • 如果检测到 item 高度不一致,再切换到 Spacer 占位法

这种混合策略,正是一些成熟虚拟列表库(如 react-window、vue-virtual-scroll-list)的做法。


🔹 5. 结论

  • 两种方案都能解决虚拟列表问题
  • Absolute 定位法 在固定高度场景下性能更优
  • Spacer 占位法 更灵活,能支持动态高度

👉 所以,选择哪种方案要根据 业务需求 来定。

相关推荐
强尼银手3 分钟前
我花一天做了个格斗游戏原型,判定全对,然后被「美术」劝退了
前端·javascript
石小石Orz13 分钟前
AI 正在蚕食我们的编码能力
前端·后端·算法
陈随易1 小时前
专注飞机 FocusFlight,两个人把番茄钟做成了一趟航班
前端·后端·程序员
总要学点什么1 小时前
第98篇:三维特效-材质线效果——给一条线换十种材质,虚线的图案只填了一半
开发语言·前端·javascript·ecmascript·gis·webgl·材质
10share2 小时前
基于大模型的 i18n 方案:把中文原文当 Key,轻松搞定多语言维护
前端·vue.js
古茗前端团队4 小时前
由 key 引发的思考
前端·javascript·react.js
kyriewen4 小时前
我扫了 422 个仓库,近一半 CI 在裸装依赖
前端·javascript·程序员
鹏多多5 小时前
AI 到底能不能独立做个产品?我拿一个小程序验证了
前端·微信小程序·ai编程
火山引擎开发者社区5 小时前
构建专属的飞书群开发助手,AgentKit Studio 一键部署 DeepSeek Harness Super-Agent
前端
啾咪orJIUMI7 小时前
Vue 3 + 高德地图封装实战:点位、区域、Loca 流光与 Vue 信息窗体
前端·vue.js