Vue 3 性能调优:大列表渲染优化的 5 种方案

Vue 3 Performance Tuning 5 Solutions for Large List Rendering

| iDev Team | 2026-08-16T07:46:00

当页面需要渲染成百上千条数据时,Vue 3 应用会出现明显卡顿。本文介绍虚拟滚动、分页加载、Web Worker 等 5 种实战方案。

When rendering hundreds or thousands of items, Vue 3 apps can lag noticeably. This article covers 5 practical solutions including virtual scrolling, pagination, and Web Workers.

问题场景 在我们最近为客户开发的库存管理系统中,商品列表页面需要展示超过 5000 条数据。使用默认的 v-for 渲染方式,页面初次加载耗时超过 3 秒,滚动时帧率掉到 15fps 以下。 方案一:虚拟滚动 虚拟滚动的核心思想是只渲染可视区域内的 DOM 元素。推荐使用 vue-virtual-scroller 库。它只会创建可见行的 DOM 节点,将 5000 条数据的渲染性能提升到与 50 条相当。 <RecycleScroller :items="list" :item-size="60" key-field="id"> <template #default="{ item }"> <div class="item">{{ item.name }}</div> </template> </RecycleScroller> 方案二:分页 + 无限滚动 使用 Intersection Observer API 实现触底加载,每次只请求 20-50 条数据。适合数据总量不确定的场景。 方案三:v-memo 指令 Vue 3.2+ 提供的 v-memo 指令可以缓存子树的渲染结果,当依赖数据未变化时跳过重新渲染。 <div v-for="item in list" :key="item.id" v-memo="[item.name, item.price]"> <ExpensiveComponent :data="item" /> </div> 方案四:Web Worker 离屏计算 将数据过滤、排序等计算密集型操作放到 Web Worker 中执行,避免阻塞主线程。 方案五:shallowRef + triggerRef 对于不需要深度响应的大列表,使用 shallowRef 替代 ref,避免 Vue 对每个元素建立深层代理。 实测对比 在 5000 条数据的场景下,虚拟滚动方案将首次渲染时间从 3.2s 降至 0.1s,内存占用从 180MB 降至 35MB。推荐优先采用虚拟滚动,其次是分页加载。


The Problem In a recent inventory management system we built for a client, the product list page needed to display over 5,000 items. Using the default v-for rendering approach, initial page load took over 3 seconds, and scrolling frame rates dropped below 15fps. Solution 1: Virtual Scrolling Virtual scrolling only renders DOM elements within the visible viewport. We recommend the vue-virtual-scroller library, which creates DOM nodes only for visible rows, making 5,000-item rendering performance comparable to 50 items. <RecycleScroller :items="list" :item-size="60" key-field="id"> <template #default="{ item }"> <div class="item">{{ item.name }}</div> </template> </RecycleScroller> Solution 2: Pagination + Infinite Scroll Use the Intersection Observer API for load-on-scroll, fetching 20-50 items per request. Best for scenarios where total data volume is unknown. Solution 3: v-memo Directive Vue 3.2+'s v-memo directive caches subtree render results, skipping re-renders when dependent data hasn't changed. <div v-for="item in list" :key="item.id" v-memo="[item.name, item.price]"> <ExpensiveComponent :data="item" /> </div> Solution 4: Web Worker Off-Thread Computing Move computation-intensive operations like filtering and sorting to Web Workers, preventing main thread blocking. Solution 5: shallowRef + triggerRef For large lists that don't need deep reactivity, use shallowRef instead of ref to avoid Vue creating deep proxies for every element. Benchmark Results With 5,000 items, virtual scrolling reduced initial render time from 3.2s to 0.1s and memory usage from 180MB to 35MB. We recommend virtual scrolling first, followed by pagination.

← Back to News