【问题标题】:Blazor UriHelper.NavigateTo is calling the page twiceBlazor UriHelper.NavigateTo 两次调用页面
【发布时间】:2019-12-31 23:53:26
【问题描述】:

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

【问题讨论】:

标签: blazor


【解决方案1】:

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

总结:

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

测试是我在索引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 会执行两次:

详细了解render modes

【讨论】:

  • 是的,你是对的。我已经更新了我的答案。请随时发表评论
  • 图形有什么问题。它使在这个线程中的导航几乎不可能。你不能做点什么吗?
  • “此行为将在 preview9 上改变”是什么意思?新行为是什么?
  • @Benni ,最后没有变化。谢谢,已解决。
【解决方案2】:

由于 dani herrera 的评论而更新:

生命周期方法 OnInitializedAsync 被调用了两次,而计数器@page 组件只被调用了一次。 此行为是设计使然。第一次执行 OnInitializedAsync 是在服务器端 Blazor 应用程序正在预渲染时,在此期间 JSInterop 不可用,因此调用 UriHelper.NavigateTo("/counter"); 会触发错误。以下代码 sn-p 描述了 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。正如您可能意识到的那样,计数器@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");
    }
}

希望这会有所帮助...

【讨论】:

  • 嗨 Issac:当我在 OnAfterRender 中添加它时,您是对的,该组件只被调用一次。唯一的问题是,如果这是一个错误或者这是正常行为,我不明白原因。再次感谢。
  • @Issac,我猜OnAfterRender 不是一个好选择,因为此时所有页面代码都已执行,在某些情况下会延迟(例如重定向到非登录用户的登录页面)。此外,您对执行 OnInitializedAsync 的解释看起来很奇怪,这只发生在预渲染时。详情请看我的帖子。
猜你喜欢
  • 1970-01-01
  • 2012-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 2021-11-30
相关资源
最近更新 更多