【问题标题】:NavigateTo not immediately showing the new pageNavigateTo 不会立即显示新页面
【发布时间】:2020-06-16 10:03:05
【问题描述】:

我有一个带有列表和编辑页面的 Blazor WebAssembly 应用程序。

当我查看实体列表并单击其中一个进行编辑时,使用 NavLink 组件,浏览器导航到编辑页面,显示我的加载器组件,直到页面加载。

效果很好。

当我在编辑页面上单击保存时,如果成功,我会导航回我的列表页面。

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");
}

我希望它会导航到 List 页面,再次显示我的 Loader 组件,然后呈现 List 页面。

但是会发生什么,它会一直停留在编辑页面上,直到呈现列表页面,我从来没有看到我的加载器组件,并且它对用户来说,看起来就像它只是挂在编辑页面上。

解决方法是在我保存完实体后在OnValidateSubmitAsync 中显示我的加载程序。

我是 Blazor 的新手,页面生命周期仍在下降,因此我的方法可能不正确。只是对这里发生的事情有点困惑,以及是否有办法强制列表页面与加载器一起显示。

希望这有点道理。 ????

【问题讨论】:

    标签: blazor blazor-webassembly


    【解决方案1】:

    根据您对@enet 回答的评论,一个可能的答案是您的列表加载页面永远不会破坏从 UI 线程释放的列表加载逻辑,因此本质上一切仍在同步运行。如果是这种情况,有两种简单的方法可以解决这个问题。

    方法一

    您可以使用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 只被调用一次。无论哪种方式都应该有效。

    如果这有帮助,请告诉我。

    附: - NavigationManager.NavigateTo() 方法也采用可选的第二个参数作为布尔值,以强制加载页面。如果设置为true,它将强制重新加载和刷新。如果您还没有尝试过,我鼓励您尝试一下,因为导航回当前页面会很有用。一个例子是复杂的表单重置之类的事情,从头开始而不是试图在整个地方反转状态更有意义,而且我遇到了一些令人沮丧的情况,这些情况通过简单的第二个参数得到了解决。这可能对你的情况也有帮助。

    【讨论】:

    • 方法 1 是我过去解决此问题的方法,到目前为止它一直有效,所以 +1
    • @NikP 成功了!不知道我会不会想到这一点!谢谢!这如何与多个部分并行工作?如果您有示例或文档,您可以指出我,将不胜感激!
    • 我会在某个时候看到关于在 Github 上发布一个模型,如果我这样做会告诉你。我不能分享我做的代码,也找不到一个例子,但要点是打开一个加载屏幕,然后启动一些等待来自各种来源的数据的任务,然后打开UI 部分,因为有数据要显示。当每个任务得到响应时,它会更新相关属性并在需要时调用await InvokeAsync(StateHasChanged),并且该部分 UI 会切换到数据呈现。
    • 感谢有关 NavigateTo 的 forceLoad: true 参数的提示!它为我解决了一个非常令人沮丧的问题,即 App.razor 的 CascadingAuthenticationState 有时在登录后看不到新的 AuthenticationState(并且会重定向回登录)。
    • 添加 true 作为 NavigateTo 的可选参数正是我所需要的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-19
    • 1970-01-01
    • 2021-09-09
    • 2011-08-10
    • 1970-01-01
    • 2011-02-05
    相关资源
    最近更新 更多