Vue 3 用虚拟滚动渲染十万行长列表:只渲染视口内的行,滚动不卡

test12026-11-0210 次阅读

长列表为什么会卡

把十万条数据直接 v-for 进 DOM,浏览器要同时维护十万个节点,首屏渲染、滚动重排、内存占用都会失控。虚拟滚动(windowing)的核心思路是:DOM 里永远只保留可视区域附近几十个节点,滚动时动态替换内容、用上下两个撑高占位元素维持原生滚动条。Vue 生态里 vue-virtual-scroller 已经把这个活儿干得很干净。

用 RecycleScroller 渲染定高列表

定高场景最简单:组件只需知道每行高度,就能算出要渲染哪一段。

// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
import VueVirtualScroller from 'vue-virtual-scroller';

createApp(App).use(VueVirtualScroller).mount('#app');
<template>
  <RecycleScroller
    class="scroller"
    :items="rows"
    :item-size="56"
    key-field="id"
    v-slot="{ item }"
  >
    <div class="row">
      <span class="title">{{ item.title }}</span>
      <span class="meta">{{ item.author }} · {{ item.date }}</span>
    </div>
  </RecycleScroller>
</template>

<script setup>
const rows = Array.from({ length: 100000 }, (_, i) => ({
  id: i,
  title: `第 ${i + 1} 条记录`,
  author: '张三',
  date: '2026-11-02',
}));
</script>

<style scoped>
.scroller { height: 600px; }
.row { height: 56px; display: flex; align-items: center; padding: 0 16px; }
</style>

动态高度怎么办

行高不一时用 DynamicScroller,它会测量真实高度并缓存。注意要给每项稳定的 key,并尽量让内容高度可预测,否则频繁测量会带来额外开销。

<DynamicScroller :items="rows" :min-item-size="56" key-field="id">
  <template #default="{ item, index }">
    <DynamicScrollerItem :item="item" :active="index < 20" :data-index="index">
      <div class="row">{{ item.title }}</div>
    </DynamicScrollerItem>
  </template>
</DynamicScroller>

踩坑提醒

  • 容器必须给定高度:虚拟滚动靠固定视口高度换算渲染区间,父元素没高度会渲染 0 行。
  • item-size 要真实:定高模式下给错值会导致滚到底部内容错位,宁可略大于真实高度。
  • 海量数据优先分页+虚拟滚动组合:十万条没问题,但如果是无限流,配合“滚动到底加载下一页”比一次塞百万条更稳。
T

test1

文章作者

长列表为什么会卡 把十万条数据直接 v-for 进 DOM,浏览器要同时维护十万个节点,首屏渲染、滚动重排、内存占用都...

分类
技术
发布时间
2026-11-02
字数
约 1758 字
阅读
10 次