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

时间:2019-09-24 07:58:24

标签: blazor blazor-server-side

因此,随着发布了asp.net core 3.0和blazor 1.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>

3 个答案:

答案 0 :(得分:6)

我用一个新的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

从结果中我们可以看到,该组件被加载了两次。

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

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

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

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

结论: 默认的RenderModeServerPrerendered,这必须表示Mvc可以将组件呈现为静态内容,以便在blazor应用程序下载并启动之前显示页面内容,然后在blazor应用程序启动时,它将花费页面内容。对于用户体验而言,这必须是一种变通方法,即浏览器用户可以等待更少的时间来查看内容。

答案 1 :(得分:1)

我在一个网站的保留页面上遇到了完全相同的问题,在该页面上有一个css动画,在开发中看起来很棒,但是当我将其投入使用时,它运行了两次。将RenderMode更改为Server当然可以解决此问题,但它的速度明显慢一些。

这很有趣,因为在完成此操作之前我永远都不会捡起它,对于最终站点,我将切换回ServerPrerendered

答案 2 :(得分:0)

您可以使用 IJSRuntime 调用一些方法或运行一些 JS 代码一次只能这样做,您可以检查属性 IsFirtRender 以仅执行一次某些方法,但它不适用于所有方法有时如果使用该方法则不会渲染前