
我有一个Blazor WebAssembly应用程序,它有一个列表和一个编辑页面,当我查看实体列表,并点击其中一个进行编辑时,使用NavLink组件,浏览器导航到编辑页面,显示我的Loader组件,直到页面加载。
当我查看一个实体列表,并点击其中一个实体进行编辑时,使用NavLink组件,浏览器导航到编辑页面,显示我的Loader组件,直到页面加载完毕。
这很好用。
当我在编辑页面上点击保存时,如果成功,我就会导航回我的列表页面。
private async Task OnValidSubmitAsync()
{
this.IsBusy = true;
var @event =
await this.EventService.UpdateByIdAsync(
this.Id,
this.EventUpdateOptions);
this.IsBusy = false;
this.NavigationManager.NavigateTo($"/teams/{this.Event.Team.Id}/events");
}
我希望发生的是它会导航到列表页,再次显示我的加载器组件,然后渲染列表页。
但是发生的情况是,它一直停留在编辑页面上,直到列表页面被渲染,我从来没有看到我的加载器组件,对用户来说,它看起来就像只是挂在编辑页面上。
变通的办法是将我的加载器显示在 OnValidateSubmitAsync当我保存完实体后,我就会把它删除。
我是Blazor的新手,还没搞清楚页面的生命周期,所以可能我的方法不正确。只是有点搞不清楚这到底是怎么回事,以及是否有办法强制列表页与加载器一起显示。
希望能说明一些问题😊
投票
根据你对@enet的回答的评论,一个可能的答案是,你的列表加载页面从来没有脱离UI线程的列表加载逻辑,所以本质上一切还是同步运行的。如果是这样的话,有两种简单的方法可以解决这个问题。
方法1
您可以使用 OnInitializedAsync 覆盖,以便在页面加载时加载列表。重要的是,你需要在加载列表前的方法中做一些事情,使运行时建立一个任务延续,并将控制权返回给UI线程,并且 Task.Delay(); 效果很好。所以你的方法是这样的。
protected override async Task OnInitializedAsync()
{
// await the delay, breaks the UI thread free from following logic
await Task.Delay(1);
// Populate your list with a background task that you await
// Assumes you already have the list initialized and just need values
ListValues = await Someservice.GetListValuesAsync();
// You may not need this call, but if so you might need to invoke it async
// Doing so will synchronize back to the UI thread
await InvokeAsync(StateHasChanged);
}
方法二
您可以使用 OnAfterRenderAsync 覆盖来加载数据。这其中的关键点是你设置你的初始UI状态显示加载组件为默认动作,然后使用这样的方法。
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
ListValues = await Someservice.GetListValuesAsync();
// Since you awaited the list population, now you can update UI
MethodToSwitchUiToListView();
// this may be needed as well
await InvokeAsync(StateHasChanged);
}
}
我倾向于使用方法2而不是方法1,因为它可以让我建立非常简单的UI来表示加载状态,然后并行加载多个部分,并在数据可用时切换UI。其次,在Blazor Server中(似乎不适用于你的情况),OnInitializedAsync方法会被调用两次,但OnAfterRender只会被调用一次。但无论哪种方式都应该是可行的。
如果有帮助,请告诉我。
P.S.- NavigationManager.NavigateTo() 方法的第二个参数也是可选的布尔值,用于强制加载页面。如果设置为 true 它强制执行强制重载和刷新。我鼓励你尝试一下,如果你还没有这样做的话,因为这对导航回到当前页面是很有用的。一个例子是像复杂的表单重设这样的事情,在这种情况下,从头开始而不是试图从头到尾地反转状态更有意义,我有一些令人沮丧的情况,通过简单的第二个参数就解决了。这个 可能 对你的情况也有帮助。
投票
我不认为这与Blazor有什么关系,至少不是直接关系。你使用的是一个异步方法,在该方法的结尾有一个对NavigateTo方法的同步调用,该方法只有在你的异步OnValidSubmitAsync方法的aysnc部分结束时才会被调用。因此,你应该在将IsBusy设置为true时立即显示Loader,当方法返回时,你将IsBusy设置为false......隐藏Loader......最后导航到你的列表页。
你可以为你的加载器创建一个自定义组件,并带有一个名为Display的布尔绑定属性,或许可以绑定到IsBusy变量上,就像这样。
@page "/edit"
<Loader Display="@IsBusy"/>
@code{
private async Task OnValidSubmitAsync()
{
this.IsBusy = true;
var @event =
await this.EventService.UpdateByIdAsync(
this.Id,
this.EventUpdateOptions);
this.IsBusy = false;
this.NavigationManager.NavigateTo($"/teams/{this.Event.Team.Id}/events");
}
}
希望能帮到你...