在使用vue-virtual-list的 DynamicScroller时,子列表项之间出现了意想不到的间距
实际效果截图:

异常的空白区域用红色圈出。模板和CSS代码如下:
<DynamicScroller
:items="msg_list"
:min-item-size="50"
id="chat-box-container">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.message]"
:data-index="index"
:key="item.id">
<div class="chat-box">
<img class="avatar" :src="item.avatar" />
<div class="chat-content-container">
<div class="name">{{ item.username }}</div>
<div class="chat-content">{{ item.content }}</div>
</div>
</div>
</DynamicScrollerItem>
</template>
</DynamicScroller>
.chat-box {
display: flex;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: aqua;
}
.chat-content-container {
margin-left: 10px;
}
.name {
color: #d1d5db;
}
.chat-content {
display: inline-block;
margin-top: 10px;
border: 2px solid rgba(185, 172, 172, 0.527);
border-radius: 6px;
background-color: rgba(185, 172, 172, 0.527);
padding: 5px 10px;
direction: ltr;
color: #d1d5db;
}
#chat-box-container {
border: 1px solid #fff;
border-radius: 10px;
padding: 10px;
margin: 20px 20px;
background-color: #36393f;
overflow: auto;
}
数据源格式:
{
"id": 1,
"userID": 2,
"avatar": "https://ts3.tc.mm.bing.net/th/id/OIP-C.7GLMYPqMlt2LgkbPsOnDIAAAAA?cb=ucfimg2ucfimg=1&rs=1&pid=ImgDetMain&o=7&rm=3",
"content": "hello,我是管理员",
"username": "admin",
"createTime": "2026-04-05T13:14:18.000+00:00",
"isDelete": 0
}
由于我在CSS中没有设置任何填充或外边距,我预计布局会遵循正常的文档流,如下图所示(不使用DynamicScroller的效果):

当我检查页面结构时,我发现把transformY属性添加到了每个子项,正是这个属性导致了间隙(因为我手动把transformY改为0 时,间隙就消失):

在这种情况下,所有项的高度都是56px。
我不知道为什么会有这样的transformY,而且上面图片所示的页面上只有四个元素,但所有数据都已渲染。这显然不正确。
我想知道我哪里出了问题,以及导致这些意外间隙和错误渲染行为的原因。
如果你能帮我,我将不胜感激 :)
解决方案
从你的代码片段来看,问题出在这里,你缺少对 vue-virtual-scroller 的必需CSS导入。我新建了一个Vue项目来测试,当我省略 import 'vue-virtual-scroller/dist/vue-virtual-scroller.css' 这一行时,结果如下:

请注意项之间的间隙,这与您在意外的 transformY 间距中所经历的情况相符。
然而,当我添加缺失的CSS导入后,虚拟滚动器就能够正确呈现:

完整可运行的代码如下:
<script setup lang="ts">
import { ref } from "vue";
import { DynamicScroller, DynamicScrollerItem } from "vue-virtual-scroller";
import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
// Fake list data generation
const generateFakeList = (count = 500) => {
const usernames = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank", "Grace"];
const avatars = [
"https://i.pravatar.cc/150?img=1",
"https://i.pravatar.cc/150?img=2",
"https://i.pravatar.cc/150?img=3",
"https://i.pravatar.cc/150?img=4",
"https://i.pravatar.cc/150?img=5",
"https://i.pravatar.cc/150?img=6",
"https://i.pravatar.cc/150?img=7",
];
const contents = [
"Hey there!",
"How are you?",
"This is a longer message to test different heights in the virtual scroller component.",
"👍",
"See you later!",
"Lorem ipsum dolor sit amet.",
"Short",
];
return Array.from({ length: count }, (_, i) => ({
id: i + 1,
username: usernames[i % usernames.length],
avatar: avatars[i % avatars.length],
content: contents[i % contents.length],
message: contents[i % contents.length], // For size-dependencies
}));
};
const msg_list = ref(generateFakeList(500));
</script>
<template>
<DynamicScroller :items="msg_list" :min-item-size="50" id="chat-box-container">
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.message]"
:data-index="index"
:key="item.id"
>
<div class="chat-box">
<img class="avatar" :src="item.avatar" />
<div class="chat-content-container">
<div class="name">{{ item.username }}</div>
<div class="chat-content">{{ item.content }}</div>
</div>
</div>
</DynamicScrollerItem>
</template>
</DynamicScroller>
</template>
<style scoped>
.chat-box {
display: flex;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: aqua;
}
.chat-content-container {
margin-left: 10px;
}
.name {
color: #d1d5db;
}
.chat-content {
display: inline-block;
margin-top: 10px;
border: 2px solid rgba(185, 172, 172, 0.527);
border-radius: 6px;
background-color: rgba(185, 172, 172, 0.527);
padding: 5px 10px;
direction: ltr;
color: #d1d5db;
}
#chat-box-container {
border: 1px solid #fff;
border-radius: 10px;
padding: 10px;
margin: 20px 20px;
background-color: #36393f;
overflow: auto;
}
</style>
添加那一行就能完全解决问题。希望这能帮到你!
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。