在Blazor应用开发中,数据展示是非常核心的场景,而空数据状态的处理直接影响用户的使用体验。当接口返回空列表、查询无结果或者数据加载失败时,如果只展示空白区域,用户会不清楚当前的状态,甚至以为应用出现了故障。因此我们需要用合理的方式处理空数据状态,让展示更友好。

基础条件渲染处理空数据
最简单的处理方式是使用Blazor的条件渲染语法,在页面中直接判断数据是否为空,分别展示不同的内容。这种方式适合简单的页面场景,不需要额外封装组件。
以下是一个简单的示例,展示用户列表时处理空数据状态:
@page "/user-list"
<h3>用户列表</h3>
@if (users == null)
{
<p>数据加载中...</p>
}
else if (users.Count == 0)
{
<div class="empty-state">
<p>暂无用户数据</p>
<button class="btn btn-primary" @onclick="LoadUsers">重新加载</button>
</div>
}
else
{
<ul>
@foreach (var user in users)
{
<li>@user.Name - @user.Email</li>
}
</ul>
}
@code {
private List<User> users;
protected override async Task OnInitializedAsync()
{
await LoadUsers();
}
private async Task LoadUsers()
{
// 模拟接口请求,这里返回空数据
await Task.Delay(500);
users = new List<User>();
}
public class User
{
public string Name { get; set; }
public string Email { get; set; }
}
}
封装通用空状态组件
如果多个页面都需要处理空数据状态,重复写条件判断逻辑会导致代码冗余,也不利于统一维护样式。我们可以封装一个通用的空状态组件,接收需要展示的内容和空状态的配置参数。
首先创建EmptyState.razor组件:
<div class="empty-state-container">
@if (IsEmpty)
{
<div class="empty-content">
@if (!string.IsNullOrEmpty(IconClass))
{
<span class="@IconClass"></span>
}
<p class="empty-text">@EmptyText</p>
@if (ShowReloadButton)
{
<button class="btn btn-outline-primary" @onclick="OnReload">
@ReloadButtonText
</button>
}
</div>
}
else
{
@ChildContent
}
</div>
@code {
[Parameter]
public bool IsEmpty { get; set; }
[Parameter]
public string EmptyText { get; set; } = "暂无数据";
[Parameter]
public string IconClass { get; set; }
[Parameter]
public bool ShowReloadButton { get; set; } = false;
[Parameter]
public string ReloadButtonText { get; set; } = "重新加载";
[Parameter]
public EventCallback OnReload { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
}
然后在页面中使用这个通用组件,只需要传入对应的参数即可:
@page "/product-list"
<h3>商品列表</h3>
<EmptyState IsEmpty="@(products == null || products.Count == 0)"
EmptyText="暂无商品数据"
ShowReloadButton="true"
ReloadButtonText="刷新商品列表"
OnReload="@LoadProducts">
<ul>
@foreach (var product in products)
{
<li>@product.Name - ¥@product.Price</li>
}
</ul>
</EmptyState>
@code {
private List<Product> products;
protected override async Task OnInitializedAsync()
{
await LoadProducts();
}
private async Task LoadProducts()
{
await Task.Delay(300);
// 模拟返回空数据
products = new List<Product>();
}
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
}
结合加载状态处理空数据
实际场景中,数据加载和空数据状态往往是关联的,我们需要同时处理加载中、加载成功有数据、加载成功无数据三种状态。可以在通用组件的基础上扩展加载状态的支持。
修改EmptyState.razor组件,增加加载状态参数:
<div class="state-container">
@if (IsLoading)
{
<div class="loading-content">
<p>数据加载中...</p>
</div>
}
else if (IsEmpty)
{
<div class="empty-content">
@if (!string.IsNullOrEmpty(IconClass))
{
<span class="@IconClass"></span>
}
<p class="empty-text">@EmptyText</p>
@if (ShowReloadButton)
{
<button class="btn btn-outline-primary" @onclick="OnReload">
@ReloadButtonText
</button>
}
</div>
}
else
{
@ChildContent
}
</div>
@code {
[Parameter]
public bool IsLoading { get; set; }
[Parameter]
public bool IsEmpty { get; set; }
[Parameter]
public string EmptyText { get; set; } = "暂无数据";
[Parameter]
public string IconClass { get; set; }
[Parameter]
public bool ShowReloadButton { get; set; } = false;
[Parameter]
public string ReloadButtonText { get; set; } = "重新加载";
[Parameter]
public EventCallback OnReload { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
}
使用该组件的页面代码可以简化为:
@page "/order-list"
<h3>订单列表</h3>
<EmptyState IsLoading="@isLoading"
IsEmpty="@(orders == null || orders.Count == 0)"
EmptyText="暂无订单记录"
ShowReloadButton="true"
OnReload="@LoadOrders">
<table class="table">
<thead>
<tr>
<th>订单号</th>
<th>金额</th>
<th>状态</th>
</tr>
</thead>
<tbody>
@foreach (var order in orders)
{
<tr>
<td>@order.OrderNo</td>
<td>¥@order.Amount</td>
<td>@order.Status</td>
</tr>
}
</tbody>
</table>
</EmptyState>
@code {
private bool isLoading = true;
private List<Order> orders;
protected override async Task OnInitializedAsync()
{
await LoadOrders();
}
private async Task LoadOrders()
{
isLoading = true;
await Task.Delay(800);
// 模拟返回空数据
orders = new List<Order>();
isLoading = false;
}
public class Order
{
public string OrderNo { get; set; }
public decimal Amount { get; set; }
public string Status { get; set; }
}
}
处理空数据的注意事项
- 空状态的文案要清晰,让用户知道当前没有数据的原因,比如是查询无结果还是数据未生成。
- 如果空状态是可恢复的,比如可以重新加载,建议提供对应的操作按钮,减少用户的操作成本。
- 统一空状态的样式,避免不同页面的空状态展示风格差异过大,影响应用的整体一致性。
- 区分空数据和加载失败的场景,加载失败时可以提供更明确的错误提示,而不是统一展示暂无数据。
通过以上几种方式,我们可以在Blazor应用中优雅地处理空数据状态,既减少重复代码,又能提升用户的使用体验,让应用的交互更加友好。