我试图通过在从服务器检索数据时显示加载指示器来改善应用程序的用户体验,但我对生命周期事件如何触发的理解似乎有问题。
在应用程序启动时,我将用户引导到带有加载微调器的登陆页面组件,同时它会从服务器预加载一些内容,然后将用户重定向到仪表板页面组件。
我希望它尽可能立即打开仪表板页面,默认内容是加载微调器。
内容方面我没有任何问题。
`OnInitializedAsync' 没有做任何事情。正是在这一点上,我希望将用户界面呈现给用户。但事实并非如此。
protected override async Task OnInitializedAsync()
{
Quote = CommonFunctions.RandomQuote();
_pageHistoryService.AddPageToHistory("/dashboard");
}
我还有一个
OnAfterRenderAsync
方法。我希望这个方法在页面加载后在后台运行。
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
GetData();
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(15));
while (!_timerCancellationToken.IsCancellationRequested && await timer.WaitForNextTickAsync())
{
GetData();
}
return;
}
}
实际上,直到
OnAfterRenderAsync
方法完成之后,UI 才会显示 DOM。这对我来说没有任何意义。
是否有什么我误解的地方,或者我需要设置一些设置或参数才能获得我想要的行为?
您的代码中有几个问题。 这是一个简单的演示,展示了重构您所显示的代码的一种方法。 代码中有注释来解释各个点。
@page "/"
@implements IDisposable
<h1>Hello, world!</h1>
Welcome to your new app.
<div class="bg-dark text-white m-2 p-2">
@if(_value is null)
{
<pre>Loading....</pre>
}
else
{
<pre>VALUE: @_value</pre>
}
</div>
@code{
private Timer? _timer;
private string? _value;
protected override Task OnInitializedAsync()
{
// Set up time to run every second with the initial run immediately
_timer = new(this.OnTimerElapsed, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));
return Task.CompletedTask;
}
private async void OnTimerElapsed(object? state)
{
// Fake async call to get data
await Task.Delay(100);
_value = DateTime.Now.ToLongTimeString();
// invoke on the UI Thread/Sync Context
await this.InvokeAsync(StateHasChanged);
}
protected override void OnAfterRender(bool firstRender)
{
// General rule: Do nothing here except JS stuff
}
// Need to implement IDisposable and dispose the timer properly
public void Dispose()
{
_timer?.Dispose();
}
}
另请查看这些答案 [以及更多],它们解释了有关 OnAfterRender 的更多信息。