为什么Blazor生命周期方法要执行两次?

为什么Blazor生命周期方法要执行两次?,blazor,blazor-server-side,Blazor,Blazor Server Side,所以随着asp.NETCore3.0和Blazor1.0的发布,我开始用blazor做一些实际的工作。在将Blazor组件代码拆分为代码隐藏时,我使用了以下代码 public class LogoutModel : BlazorComponent { } 不幸的是BlazorComponent已经不存在了,所以我转到ComponentBase。不确定这一变化是什么时候发生的 现在,我的其余代码如下所示 public class LogoutModel : ComponentBase

所以随着asp.NETCore3.0和Blazor1.0的发布,我开始用blazor做一些实际的工作。在将Blazor组件代码拆分为代码隐藏时,我使用了以下代码

 public class LogoutModel : BlazorComponent
    {
}
不幸的是BlazorComponent已经不存在了,所以我转到ComponentBase。不确定这一变化是什么时候发生的

现在,我的其余代码如下所示

 public class LogoutModel : ComponentBase
    {

        protected override async Task OnInitializedAsync()
        {
        }

        protected override async Task OnParametersSetAsync()
        {
        }
    }
我注意到生命周期方法是按以下顺序执行的 OnInitializedAsync() OnParametersSetAsync() OnInitializedAsync() OnParametersSetAsync()

我不太清楚为什么每个方法执行两次

这就是我的Blazor文件的样子

@page  "/account/logout"
@inherits LogoutModel

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    Logout page
</body>
</html>
@page”/account/logout
@继承LogoutModel
注销页面

我用一个全新的
blazorserver
项目做了一个测试,记录了调用生命周期方法的时间,得到了以下输出:

info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\Alsein\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\repos\HelloWorld
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/_Host'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/_Host"}. Executing page /_Host
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
crit: HelloWorld.MyBase[0]
      OnInitializedAsync
crit: HelloWorld.MyBase[0]
      OnParameterSetAsync
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /_Host in 122.3724ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/_Host'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 216.7341ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/css/site.css
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/_framework/blazor.server.js
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/css/bootstrap/bootstrap.min.css
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/css/site.css'. Physical path: 'D:\repos\HelloWorld\wwwroot\css\site.css'
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/_framework/blazor.server.js'. Physical path: 'N/A'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 44.733000000000004ms 200 text/css
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/css/bootstrap/bootstrap.min.css'. Physical path: 'D:\repos\HelloWorld\wwwroot\css\bootstrap\bootstrap.min.css'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 55.3613ms 200 text/css
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 55.569900000000004ms 200 application/javascript
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/css/open-iconic/font/css/open-iconic-bootstrap.min.css
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/css/open-iconic/font/css/open-iconic-bootstrap.min.css'. Physical path: 'D:\repos\HelloWorld\wwwroot\css\open-iconic\font\css\open-iconic-bootstrap.min.css'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 4.5189ms 200 text/css
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 POST https://localhost:5001/_blazor/negotiate text/plain;charset=UTF-8 0
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/css/open-iconic/font/fonts/open-iconic.woff
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/css/open-iconic/font/fonts/open-iconic.woff'. Physical path: 'D:\repos\HelloWorld\wwwroot\css\open-iconic\font\fonts\open-iconic.woff'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 4.3562ms 200 application/font-woff
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/_blazor/negotiate'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/_blazor/negotiate'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 24.7409ms 200 application/json
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/_blazor?id=7oyJvbydrUy9tqlsH_DHzQ
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/_blazor'
crit: HelloWorld.MyBase[0]
      OnInitializedAsync
crit: HelloWorld.MyBase[0]
      OnParameterSetAsync
从结果可以看出,组件加载了两次

  • 当页面由
    /\u Host
    请求和处理时,它第一次作为简单的Mvc组件直接加载,该页面必须在
    \u Host.cshtml
    中使用以下代码指定,该代码第一次调用生命周期方法:
@(等待Html.RenderComponentAsync(RenderMode.ServerPrerendered))
  • 然后加载资源,包括
    blazor.server.js

  • 然后blazor应用程序开始渲染

  • 然后将该组件作为blazor组件加载,其中第二次调用生命周期方法

尝试将
RenderMode.ServerPrerendered
替换为
RenderMode.Server
,然后它会按预期运行,即只调用一次生命周期方法(当blazor应用程序启动时)

结论:
默认的
RenderMode
ServerPrerendered
,这意味着Mvc可以将组件呈现为静态内容,以便在blazor应用程序下载和启动之前显示页面内容,然后当blazor应用程序启动时,它接管页面内容。这必须是一个用户体验的解决办法,浏览器用户可以等待更少的时间来查看内容。

我在一个网站的保留页上遇到了完全相同的问题,在那里我有一个小css动画,它在开发中看起来很棒,但当我把它放在现场时,它运行了两次。将RenderMode更改为Server当然可以解决此问题,但速度明显较慢


有趣的是,在我做这件事之前,我永远不会拿起这个,对于最后一个站点,我将切换回ServerPrerendered

您使用的是哪种托管模式?我正在使用blazor Server感谢您花时间研究这个问题,这对我帮助很大。谢谢,如果这是Nuxt.js,这将类似于混合模式,其中,组件或页面的某些部分可以在服务器上可控地预呈现,以加快速度,或使用某些仅在服务器端可用(或应该仅在服务器端可用)的服务。必须有一种方法来检查组件的呈现位置,在lifecycle方法中,我想我在某处看到了它,但我现在不记得了。然后,您可以简单地执行if检查并相应地继续。我切换到“服务器”,但仍然调用了两次。受保护的重写异步任务OnInitializedAsync(){await GetData()}???
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))