我为Blazor的加载状态管理创建了一个非常简单的组件。 (.Net核心3.1,添加了部分类支持)
Shared / LoadContainer.razor
@if (State == LoadContainerState.Initial)
{
@Initial
}
else if (State == LoadContainerState.Loading)
{
@Loading
}
else if (State == LoadContainerState.Loaded)
{
@Loaded
}
else if (State == LoadContainerState.Error)
{
@ErrorContent
}
Shared / LoadContainer.razor.cs
using Microsoft.AspNetCore.Components;
namespace BlazorUI.Shared
{
public enum LoadContainerState { Initial, Loading, Loaded, Error }
public partial class LoadPageContainer
{
[Parameter]
public LoadContainerState State { get; set; }
[Parameter]
public RenderFragment? Initial { get; set; }
[Parameter]
public RenderFragment? Loading { get; set; }
[Parameter]
public RenderFragment? Loaded { get; set; }
[Parameter]
public RenderFragment? ErrorContent { get; set; }
}
}
它对于具有所有四个状态的应用程序都很好。
@using BlazorUI.Shared
<LoadPageContainer State="state">
<Initial>
<p>
Please enter inputs.
</p>
</Initial>
<Loading>
<div class="lds-hourglass">Loading....</div>
</Loading>
<Loaded>
Show the data
</Loaded>
<ErrorContent>
<p style="color:red">@errorMsg</p>
</ErrorContent>
</LoadPageContainer>
但是,如果我尝试加载数据并更改OnInitializedAsync()
中的状态,它会保持初始状态吗?
LoadContainerState state = LoadContainerState.Initial;
protected override async Task OnInitializedAsync()
{
state = LoadContainerState.Loading; // Doesn't switch to loading
var r = await ReadDataFromSlowDatabase();
if (r.IsFailure) { error = r.Error; }
else { vm = r.Value; error = null; }
state = LoadContainerState.Loaded; // Doesn't switch to loaded
// StateHasChanged(); // Not working
}
答案 0 :(得分:0)
这是因为您将局部类命名为LoadPageContainer,文件名为LoadContainer.razor.cs和LoadContainer.razor。将类名更改为LoadContainer或将文件名更改为LoadPageContainer.razor.cs和LoadPageContainer.razor.cs
不带扩展名的文件名是组件名称和类型。
偶然地,在OnInitializedAsync中调用StateHasChanged方法是多余的,因为组件总是在此方法的执行流程结束时重新呈现。
为什么将Renderfragment属性定义为可为空?
LoadContainer.razor
@if (State == LoadPageContainerState.Initial)
{
@Initial
}
else if (State == LoadPageContainerState.Loading)
{
@Loading
}
else if (State == LoadPageContainerState.Loaded)
{
@Loaded
}
else if (State == LoadPageContainerState.Error)
{
@ErrorContent
}
LoadContainer.razor.cs
public enum LoadPageContainerState { Initial, Loading, Loaded, Error }
public partial class LoadContainer
{
[Parameter]
public LoadPageContainerState State { get; set; }
[Parameter]
public RenderFragment? Initial { get; set; }
[Parameter]
public RenderFragment? Loading { get; set; }
[Parameter]
public RenderFragment? Loaded { get; set; }
[Parameter]
public RenderFragment? ErrorContent { get; set; }
}
用法(Index.razor)
@page "/"
<h1>Hello, world!</h1>
Welcome to your new app.
<LoadContainer State="state">
<Initial>
<p>
Please enter inputs.
</p>
</Initial>
<Loading>
<div class="lds-hourglass">Loading....</div>
</Loading>
<Loaded>
Show the data
</Loaded>
<ErrorContent>
<p style="color:red">@errorMsg</p>
</ErrorContent>
</LoadContainer>
@code{
private string errorMsg = "ErrorRRRRRRRRRRRR";
private LoadPageContainerState state;
protected override async Task OnInitializedAsync()
{
// This is done so that you can see "Please enter inputs."
await Task.Delay(2000);
// After two second you'll see "Loading...."
state = LoadPageContainerState.Loading;
// must call StateHasChanged to perform a re-render
StateHasChanged();
// Delay for 5 seconds and then display "Show the data"
await Task.Delay(5000);
//if (r.IsFailure) { error = r.Error; }
//else { vm = r.Value; error = null; }
state = LoadPageContainerState.Loaded;
}
}