为什么用了虚拟滚动后列表滚动还是卡顿?

司徒新霞 阅读 41

我在一个Vue项目里用v-for渲染2000条列表项,滚动特别卡。试过vue-virtual-scroller但没改善,控制台没报错,FPS还是掉到30以下。这是我的代码:


<template>
  <VirtualList :size="50" :estimated="2000">
    <div v-for="item in items" :key="item.id">
      {{ item.content }}
    </div>
  </VirtualList>
</template>

检查过元素高度计算没问题,也设置了固定高度容器。难道是key没写对?或者虚拟滚动有其他隐藏配置没设置?

我来解答 赞 7 收藏
二维码
手机扫码查看
2 条解答
UX丽丽
UX丽丽 Lv1
你这代码问题不大,卡顿大概率是虚拟滚动没正确绑定滚动容器。试试在VirtualList加上:wrap-size="containerHeight"或者检查下父容器有没有设置固定高度。另外v-for套在VirtualList里面可能渲染没拦截住,改成v-for包裹VirtualList试试:

<template>
<div v-for="item in items" :key="item.id">
<VirtualList :size="50" :estimated="2000" :wrap-size="containerHeight">
<div>{{ item.content }}</div>
</VirtualList>
</div>
</template>
点赞 6
2026-02-08 11:02
百里瑞芹
你这个问题,其实挺常见的。虚拟滚动确实能解决大量 DOM 节点卡顿的问题,但用得不对的话,它也照样拉胯。

先说你的代码问题:

<VirtualList :size="50" :estimated="2000">
<div v-for="item in items" :key="item.id">
{{ item.content }}
</div>
</VirtualList>


你虽然套了个 ,但里面
这句,其实是把所有 items 都渲染出来了,**虚拟滚动压根没生效**。vue-virtual-scroller 的组件是需要每个 item 被单独包裹成一个组件或者用 v-for 内部循环生成 item 的。

正确写法应该是这样:

<VirtualList :data="items" :item-size="50" :wrap-size="2000">
<template #default="{ item }">
<div :key="item.id">
{{ item.content }}
</div>
</template>
</VirtualList>


注意点:

- 要通过 data 传入列表数据
- 用 #default="{ item }" 的方式来渲染每一项
- 每个 item 的高度尽量统一,或准确提供 item-size 或使用 dynamic 模式(但会损耗性能)
- 如果内容高度不一致,记得加 :dynamic="true",但 FPS 可能还是会受影响

FPS 掉到 30 以下,说明渲染压力大,除了正确使用虚拟滚动外,还可以检查:

- 列表项里有没有复杂的计算属性或嵌套组件
- 使用 key 时是否稳定(不要用 index,推荐用唯一 id)
- 容器本身有没有设置了固定高度或最大高度,否则虚拟滚动无法计算可视区域
- 如果是移动端,某些浏览器对 transform 渲染支持差,可能会卡顿

另外,你提到“控制台没报错”,这不能说明没问题。很多性能问题都是静默的,可以打开 Chrome DevTools 的 Performance 面板做帧分析,看看是哪一块在拖慢渲染。

总之,你不是 key 写得不对,而是压根没用对虚拟滚动 😅。改完上面那段代码,再观察 FPS,应该就能明显提升。如果还有卡顿,再查 item 内容复杂度和浏览器渲染机制的问题。
点赞 5
2026-02-04 23:07