Blazor UriHelper.NavigateTo两次调用页面

时间:2019-08-27 19:00:41

标签: blazor

我在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中的计数器路由时仅调用一次计数器页面

2 个答案:

答案 0 :(得分:2)

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

enter image description here

总结:

启用预渲染(默认情况下)时,两次调用了by design进行了预置页面的OnInitializedAsync。因此,您的重定向语句执行两次。

要测试的是我在索引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;
    }
}

然后我使用预渲染和从应用程序调用页面(不进行预渲染)。注意,当我强制重新加载(推荐)时,OnInitializedAsync执行了两次:

enter image description here

详细了解render modes

答案 1 :(得分:-1)

由于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);
        }

See more here。您可能意识到,没有调用counter @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");
    }
}

希望这对您有帮助...