Vue列表滚动卡顿,虚拟滚动没效果怎么办?

Mc.溪纯 阅读 29

用Vue做商品列表页时,页面滚动特别卡顿,尝试用v-if做了虚拟滚动但没效果。

代码是这样写的:

{
data() {
return {
items: Array.from({length: 200}, (_, i) => i),
viewportHeight: 0,
containerTop: 0
}
},
methods: {
handleScroll() {
this.containerTop = this.$refs.list.offsetTop
}
}
}

计算可视区域的时候总拿错容器位置,滚动时DOM还在频繁重渲染,求大神指条明路

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
W″宁宁
你这虚拟滚动写法有点问题,我一般直接用 vue-virtual-scroller 这个库,省事又稳定。如果非得自己写,参考这个:

data() {
return {
items: Array.from({ length: 200 }, (_, i) => i),
visibleItems: [],
itemHeight: 50,
scrollTop: 0
};
},
methods: {
handleScroll() {
this.scrollTop = this.$refs.container.scrollTop;
const start = Math.floor(this.scrollTop / this.itemHeight);
this.visibleItems = this.items.slice(start, start + 10);
}
},
mounted() {
this.$refs.container.addEventListener('scroll', this.handleScroll);
}


再优化下样式和高度就流畅了,别自己造轮子太复杂。
点赞 8
2026-02-02 04:03
UX-沐希
UX-沐希 Lv1
你这个虚拟滚动实现有点问题,光靠 v-if 是不够的。复制这个完整实现:

export default {
data() {
return {
items: Array.from({ length: 200 }, (_, i) => Item ${i}),
itemHeight: 50, // 每个item的高度
visibleCount: 10, // 可视区域显示多少条
startIndex: 0,
containerHeight: 500 // 容器高度
};
},
computed: {
endIndex() {
return this.startIndex + this.visibleCount;
},
visibleItems() {
return this.items.slice(this.startIndex, this.endIndex);
}
},
methods: {
handleScroll(event) {
constscrollTop = event.target.scrollTop;
this.startIndex = Math.floor(scrollTop / this.itemHeight);
}
},
template:
<div
style="height:{{containerHeight}}px;overflow:auto;"
@scroll="handleScroll"
>
<div
:style="{ height:
${items.length * itemHeight}px }"
>
<div
v-for="(item, index) in visibleItems"
:key="index"
:style="{ height:
${itemHeight}px }"
>
{{item}}
</div>
</div>
</div>

};


重点说下:
1. 固定每个item的高度 itemHeight,这样才能通过 scrollTop 快速计算出 startIndex
2. 不要渲染全部 DOM,只渲染可视区域的内容,用 slice 截取需要的部分。
3. 外层包裹一个假高度的 div,用来撑起滚动条。

照着这个改,基本不会卡了。如果还卡顿,检查下样式或者浏览器性能瓶颈吧。
点赞 7
2026-01-29 17:23