C# Blazor 显示微调器直到 foreach 循环完成
C# Blazor show spinner until foreach loop is finished
我有一个页面加载了 C# Blazor 中的项目列表。我试图找出一种微调器显示的方式,直到我的 foreach 循环迭代了所有列表项。这是我当前的代码:
@foreach (var f in FlyersState.Value.Flyers)
{
@if (isLoading)
{
<div class="spinner"></div>
}
else
{
<tr>
<td class="clickable" @onclick="()=>OpenFlyerDetails(f)">
@f.DealNo
<a href="flyers/@(f.Id)" target="_blank"><i class="fas fa-external-link-alt"></i></a>
</td>
<td>@f.Range</td>
<td>@f.Id</td>
<td>
<a class=" float-right" href="" data-target="#flyerModal" data-toggle="modal" @onclick="(() => EditFlyer(f))">
<i class="fas fa-edit"></i>
</a>
</td>
<td>
<a class=" float-right" href="" data-target="#confirmModal" data-toggle="modal" @onclick="(() => ShowDeleteConfirmAtionDialog(f))">
<i class="far fa-trash-alt"></i>
</a>
</td>
</tr>
}
}
我的页面是这样初始化的:
private Flyer selectedFlyer => FlyersState.Value.SelectedFlyer;
private bool isLoading = true;
Flyer flyer = new Flyer();
protected override void OnInitialized()
{
base.OnInitialized();
Dispatcher.Dispatch(new LoadFlyersAction());
}
我 运行 遇到的问题是,当循环完成迭代我的 table 时,我不确定如何将 isLoading 变为 false。任何帮助将不胜感激。
我会这样做:
<div id="spinner" class="@(spinner-state)">
@foreach (var f in FlyersState.Value.Flyers)
{
@if (isLoading)
{
<div class="spinner"></div>
}
else
{
<tr>
<td class="clickable" @onclick="()=>OpenFlyerDetails(f)">
@f.DealNo
<a href="flyers/@(f.Id)" target="_blank"><i class="fas fa-external-link-alt"></i></a>
</td>
<td>@f.Range</td>
<td>@f.Id</td>
<td>
<a class=" float-right" href="" data-target="#flyerModal" data-toggle="modal" @onclick="(() => EditFlyer(f))">
<i class="fas fa-edit"></i>
</a>
</td>
<td>
<a class=" float-right" href="" data-target="#confirmModal" data-toggle="modal" @onclick="(() => ShowDeleteConfirmAtionDialog(f))">
<i class="far fa-trash-alt"></i>
</a>
</td>
</tr>
}
}
然后,在代码中
private string spinner-state = "show-spinner";
private Flyer selectedFlyer => FlyersState.Value.SelectedFlyer;
private bool isLoading = true;
Flyer flyer = new Flyer();
protected override void OnInitialized()
{
base.OnInitialized();
Dispatcher.ShutdownStarted += HideSpinner();
Dispatcher.Dispatch(new LoadFlyersAction());
}
void HideSpinner(object sender, DispatcherShutdownEventArgs e)
{
spinner-state = "hide-spinner";
}
工作 Blazor 演示
我创建了一个可用的 Blazor Fiddle,您可以将其用作指南 here。它模拟了一个很长的 运行 数据查询,并在 运行.
时显示一个加载图标
您的代码的主要问题是 if(isLoading)
条件位于构建 table 的循环内。这些需要通过将 if 语句移到循环外来反转。然后它将根据 isLoading
.
的值正确显示加载图标或显示 table
所以不是这个逻辑:
loop over data {
if loading
show icon
else
show table rows
end
}
您希望它看起来像这样:
if (loading)
show icon
else
loop over data {
show table rows
}
end
我建议的另一个更改是将数据加载到 OnInitializedAsync()
或 OnAfterRenderAsync()
中。它们都是异步的,你可以“等待”你的数据而不需要额外的 Dispatcher
。请注意,由于 pre-rendering,Blazor 服务器会调用初始化两次,如果您有较长的 运行 查询,您可能希望避免这种情况。然而,解决方案超出了问题的范围。
我有一个页面加载了 C# Blazor 中的项目列表。我试图找出一种微调器显示的方式,直到我的 foreach 循环迭代了所有列表项。这是我当前的代码:
@foreach (var f in FlyersState.Value.Flyers)
{
@if (isLoading)
{
<div class="spinner"></div>
}
else
{
<tr>
<td class="clickable" @onclick="()=>OpenFlyerDetails(f)">
@f.DealNo
<a href="flyers/@(f.Id)" target="_blank"><i class="fas fa-external-link-alt"></i></a>
</td>
<td>@f.Range</td>
<td>@f.Id</td>
<td>
<a class=" float-right" href="" data-target="#flyerModal" data-toggle="modal" @onclick="(() => EditFlyer(f))">
<i class="fas fa-edit"></i>
</a>
</td>
<td>
<a class=" float-right" href="" data-target="#confirmModal" data-toggle="modal" @onclick="(() => ShowDeleteConfirmAtionDialog(f))">
<i class="far fa-trash-alt"></i>
</a>
</td>
</tr>
}
}
我的页面是这样初始化的:
private Flyer selectedFlyer => FlyersState.Value.SelectedFlyer;
private bool isLoading = true;
Flyer flyer = new Flyer();
protected override void OnInitialized()
{
base.OnInitialized();
Dispatcher.Dispatch(new LoadFlyersAction());
}
我 运行 遇到的问题是,当循环完成迭代我的 table 时,我不确定如何将 isLoading 变为 false。任何帮助将不胜感激。
我会这样做:
<div id="spinner" class="@(spinner-state)">
@foreach (var f in FlyersState.Value.Flyers)
{
@if (isLoading)
{
<div class="spinner"></div>
}
else
{
<tr>
<td class="clickable" @onclick="()=>OpenFlyerDetails(f)">
@f.DealNo
<a href="flyers/@(f.Id)" target="_blank"><i class="fas fa-external-link-alt"></i></a>
</td>
<td>@f.Range</td>
<td>@f.Id</td>
<td>
<a class=" float-right" href="" data-target="#flyerModal" data-toggle="modal" @onclick="(() => EditFlyer(f))">
<i class="fas fa-edit"></i>
</a>
</td>
<td>
<a class=" float-right" href="" data-target="#confirmModal" data-toggle="modal" @onclick="(() => ShowDeleteConfirmAtionDialog(f))">
<i class="far fa-trash-alt"></i>
</a>
</td>
</tr>
}
}
然后,在代码中
private string spinner-state = "show-spinner";
private Flyer selectedFlyer => FlyersState.Value.SelectedFlyer;
private bool isLoading = true;
Flyer flyer = new Flyer();
protected override void OnInitialized()
{
base.OnInitialized();
Dispatcher.ShutdownStarted += HideSpinner();
Dispatcher.Dispatch(new LoadFlyersAction());
}
void HideSpinner(object sender, DispatcherShutdownEventArgs e)
{
spinner-state = "hide-spinner";
}
工作 Blazor 演示
我创建了一个可用的 Blazor Fiddle,您可以将其用作指南 here。它模拟了一个很长的 运行 数据查询,并在 运行.
时显示一个加载图标您的代码的主要问题是 if(isLoading)
条件位于构建 table 的循环内。这些需要通过将 if 语句移到循环外来反转。然后它将根据 isLoading
.
所以不是这个逻辑:
loop over data {
if loading
show icon
else
show table rows
end
}
您希望它看起来像这样:
if (loading)
show icon
else
loop over data {
show table rows
}
end
我建议的另一个更改是将数据加载到 OnInitializedAsync()
或 OnAfterRenderAsync()
中。它们都是异步的,你可以“等待”你的数据而不需要额外的 Dispatcher
。请注意,由于 pre-rendering,Blazor 服务器会调用初始化两次,如果您有较长的 运行 查询,您可能希望避免这种情况。然而,解决方案超出了问题的范围。