在Blazor应用里处理长列表场景时,直接渲染全部数据会带来严重的性能损耗,Virtualize组件通过虚拟化渲染机制可以有效解决这个问题,它仅生成当前视口内可见的列表元素,大幅降低DOM渲染压力。

Virtualize组件的核心原理
Virtualize组件的工作逻辑是监听容器的滚动事件,计算当前可视区域的范围,然后根据列表项的高度和总数据量,只渲染落在可视区域内的数据项。当列表滚动时,组件会动态更新渲染的内容,替换掉已经滚出可视区域的元素,整个过程对用户来说是无感知的。
这种方式相比传统一次性渲染所有列表项,DOM节点数量可以减少90%以上,尤其是在数据量达到上万条的场景下,性能提升效果非常明显。
基础使用方式
使用Virtualize组件首先需要准备数据源,然后通过Items参数绑定数据,在子模板中定义单个列表项的渲染逻辑。以下是一个简单的示例,展示如何渲染一个包含10000条数据的用户列表:
// 用户数据模型
public class UserInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
// 页面组件代码
@page "/long-list"
<h3>用户列表(共10000条)</h3>
<Virtualize Items="UserList" Context="user">
<ItemContent>
<div class="list-item">
<p>ID: @user.Id</p>
<p>姓名: @user.Name</p>
<p>邮箱: @user.Email</p>
</div>
</ItemContent>
</Virtualize>
@code {
// 生成10000条模拟用户数据
private List<UserInfo> UserList { get; set; } = new();
protected override void OnInitialized()
{
for (int i = 1; i <= 10000; i++)
{
UserList.Add(new UserInfo
{
Id = i,
Name = $"用户{i}",
Email = $"user{i}@ipipp.com"
});
}
}
}
上面的代码中,Context="user"指定了子模板中数据项的上下文名称,ItemContent模板定义了单个列表项的渲染结构。运行后可以看到,即使有10000条数据,初始渲染的DOM节点也只有可视区域内的几十个,滚动时才会动态加载新的内容。
自定义列表项高度与加载状态
默认情况下Virtualize组件会假设所有列表项高度相同,如果列表项高度不固定,需要通过ItemSize参数设置预估高度,同时可以自定义加载状态的显示内容。
设置预估高度
当列表项高度不一致时,可以设置ItemSize为平均高度,组件会基于这个值计算可视区域需要渲染的项数:
<Virtualize Items="DynamicHeightList" ItemSize="80" Context="item">
<ItemContent>
<div class="dynamic-item" style="height: @(item.Height)px">
@item.Content
</div>
</ItemContent>
</Virtualize>
自定义加载占位内容
当数据需要异步加载时,可以使用Placeholder模板定义加载中的占位内容:
<Virtualize Items="AsyncUserList" Context="user">
<ItemContent>
<div class="list-item">
@user.Name
</div>
</ItemContent>
<Placeholder>
<div class="loading-placeholder">
正在加载数据...
</div>
</Placeholder>
</Virtualize>
异步数据加载场景适配
如果长列表的数据是分页异步加载的,Virtualize组件也支持通过ItemsProvider参数自定义数据加载逻辑,实现滚动到底部自动加载下一页数据的效果:
@page "/async-long-list"
<Virtualize ItemsProvider="LoadUsersAsync" Context="user">
<ItemContent>
<div class="list-item">
<p>@user.Name</p>
</div>
</ItemContent>
</Virtualize>
@code {
private int currentPage = 1;
private const int PageSize = 50;
private async Task<ItemsProviderResult<UserInfo>> LoadUsersAsync(ItemsProviderRequest request)
{
// 计算需要加载的起始索引和数量
var startIndex = request.StartIndex;
var count = Math.Min(request.Count, PageSize);
// 模拟异步加载数据
await Task.Delay(500);
var users = new List<UserInfo>();
for (int i = startIndex; i < startIndex + count; i++)
{
users.Add(new UserInfo
{
Id = i,
Name = $"异步加载用户{i}",
Email = $"async_user{i}@ipipp.com"
});
}
// 返回加载的数据和总数据量,这里假设总共有10000条
return new ItemsProviderResult<UserInfo>(users, 10000);
}
}
上面的代码中,ItemsProvider参数接收一个返回ItemsProviderResult的异步方法,组件会根据滚动位置自动调用该方法加载对应范围的数据,无需手动处理分页逻辑。
使用注意事项
- Virtualize组件需要放在具有固定高度的可滚动容器内,否则无法正确计算可视区域范围,可以给父容器设置
height和overflow-y: auto样式。 - 如果列表项中有复杂的DOM结构或者大量事件绑定,建议做好组件的复用和事件销毁,避免内存泄漏。
- 当数据量较小(比如少于100条)时,不需要使用Virtualize组件,因为虚拟化本身也会带来少量的性能开销,小数据量下反而可能降低性能。
通过合理使用Virtualize组件,开发者可以在Blazor应用中轻松应对长列表的性能问题,让页面在大数据场景下依然保持流畅的交互体验。
BlazorVirtualize组件长列表优化虚拟化渲染修改时间:2026-07-17 10:15:31