6

我在 Preview 8 中创建了一个新的 Blazor 服务器端应用程序。当我调用 UriHelper.NavigateTo 从 Index.razor 页面转到计数器页面时,计数器页面被调用了两次。

在 Index.razor 页面中,我有以下代码:

@code{

    protected async override Task OnInitializedAsync()
    {
        UriHelper.NavigateTo("/counter");
    }

}

然后在计数器页面中,我添加了以下带有断点的代码:

protected override void OnInitialized()
{

}

我的期望是在 NavigateTo 调用 Index.razor 中的计数器路由时只调用一次计数器页面

4

2 回答 2

5

这种行为是因为预渲染功能。请注意,当您打开counter page(加载两次)时,如果您单击Home,则只会触发一次执行:

在此处输入图像描述

总结:

启用预渲染时(默认情况下),预渲染页面会被 designOnInitializedAsync 调用两次。因此,您的重定向语句会执行两次。

为了测试,我在 index 上写了这段代码OnInitializedAsync

@page "/"
@inject IUriHelper UriHelper

<h1>Hello, world!</h1>

Welcome to your new app.

@code{

    protected async override Task OnInitializedAsync()
    {
        System.Console.WriteLine("_*   ");
        System.Console.WriteLine("_**************************");
        System.Console.WriteLine("_***** Pre render ******");
        System.Console.WriteLine("_**************************");
        System.Console.WriteLine("_   ");
        return;
    }
}

我使用预渲染和从应用程序(没有预渲染)调用页面。注意到当我强制重新加载(prerended)时,OnInitializedAsync执行了两次:

在此处输入图像描述

了解有关渲染模式的更多信息。

于 2019-08-28T16:25:45.257 回答
4

由于 dani herrera 的评论而更新:

生命周期方法 OnInitializedAsync 被调用两次,但计数器 @page 组件仅被调用一次。此行为是设计使然。第一次执行 OnInitializedAsync 是在服务器端 Blazor 应用程序正在预渲染时,在此期间,JSInterop 不可用,因此调用UriHelper.NavigateTo("/counter");会触发错误。以下代码片段描述了 Blazor 当前如何处理此类情况:

protected override void NavigateToCore(string uri, bool forceLoad)
        {
            Log.RequestingNavigation(_logger, uri, forceLoad);

            if (_jsRuntime == null)
            {
                var absoluteUriString = ToAbsoluteUri(uri).ToString();
                throw new NavigationException(absoluteUriString);
            }

            _jsRuntime.InvokeAsync<object>(Interop.NavigateTo, uri, forceLoad);
        }

在这里查看更多。正如您可能意识到的,计数器@page 组件没有被调用,并且引发了异常。

预渲染完成后,客户端 SignalR 建立与服务器的连接,并渲染您的应用程序。这一次(第二次调用 OnInitializedAsync 方法)UriHelper.NavigateTo("/counter");正确执行,我们愉快地导航到计数器页面(第一次)

您可以使用 OnAfterRender 方法作为解决方法,并且您应该验证 SignalR 是否已经建立了与服务器的连接;即预渲染过程已经完成。

@page "/"
@using Microsoft.JSInterop
@inject IComponentContext ComponentContext
@inject IJSRuntime jsRuntime

<p>Navigate to the counter component.</p>

@code{

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (!ComponentContext.IsConnected) return;

         UriHelper.NavigateTo("/counter");
    }
}

希望这可以帮助...

于 2019-08-27T19:14:15.663 回答