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

2024-04-13

因此,随着 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()
    {
    }
}

我注意到生命周期方法按以下顺序执行

  1. OnInitializedAsync()
  2. OnParametersSetAsync()
  3. OnInitializedAsync()
  4. 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>

TL;DR

这是因为预渲染机制将组件初始化为主机页面的一部分_Host.cshtml,这样第一个 http 请求将生成一个主机页面,该主机页面不仅作为 blazor 应用程序的脚本加载器,而且还具有静态渲染的视图。因此,用户可以看到初始视图,而不必等待大致以下步骤:

  • WebSocket 连接由 SignalR 建立。

  • 第一组渲染指令是从服务器接收的。

  • 渲染指令应用于视图。

这不仅可以缩短用户看到初始视图之前的响应延迟,而且还可以受益SEO https://en.wikipedia.org/wiki/Search_engine_optimization#Getting_indexed。 blazor 应用程序正常启动后,预渲染视图将被真实的 blazor 组件替换。

新项目模板中默认启用预渲染功能,因此您必须选择以下选项之一:

  • 正确处理该组件已预渲染的情况(可能通过检查是否IJSRuntime可以通过依赖注入来解决)。

  • 通过修改禁用预渲染功能_Host.cshtml, 替换

<component type="typeof(App)" render-mode="ServerPrerendered" />

with

<component type="typeof(App)" render-mode="Server" />

对于旧版本,替换

@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))

with

@(await Html.RenderComponentAsync<App>(RenderMode.Server))

原来的答案

我用全新的进行了测试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

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

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

  • 然后 Blazor 应用开始渲染。

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

尝试更换RenderMode.ServerPrerendered with RenderMode.Server,然后它的行为符合预期,即生命周期方法仅被调用一次(当 blazor 应用程序启动时)。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Blazor 生命周期方法会执行两次? 的相关文章

  • 检测到 NuGet 包的版本冲突

    我正在开发 ASP Net core 2 1 Web 应用程序项目 我的解决方案中有 1 个项目和 3 个其他库 它是高级架构 数据访问层 DAL 业务层 BL 公共层 CL 所以我需要添加引用来连接一些库和项目 我已经添加了CL参考我的项
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set
  • 在 C++ 中分割大文件

    我正在尝试编写一个程序 该程序接受一个大文件 任何类型 并将其分成许多较小的 块 我想我已经有了基本的想法 但由于某种原因我无法创建超过 12 kb 的块大小 我知道谷歌等上有一些解决方案 但我更感兴趣的是了解这个限制的根源是什么 然后实际
  • 为什么基类必须有一个带有 0 个参数的构造函数?

    这不会编译 namespace Constructor0Args class Base public Base int x class Derived Base class Program static void Main string a
  • 当我单击 C# 中的“取消”按钮时重定向到新页面(Web 部分)

    Cancel button tc new TableCell btnCancel new Button btnCancel Text Cancel btnCancel Click new EventHandler btnCanel Clic
  • 捕获 foreach 条件中抛出的异常

    我有一个foreach在 foreach 本身的条件下循环期间中断的循环 有没有办法try catch抛出异常然后继续循环的项 这将运行几次 直到异常发生然后结束 try foreach b in bees exception is in
  • try-catch 中未处理的异常

    try list from XElement e in d Descendants wix File where e Attribute Name Value Contains temp Name e Parent Parent Attri
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • ZLIB 解压缩

    我编写了一个小型应用程序 该应用程序应该解压缩以 gzip deflate 格式编码的数据 为了实现这一点 我使用 ZLIB 库 使用解压缩功能 问题是这个功能不起作用 换句话说 数据不是未压缩的 我在这里发布代码 int decompre
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • 是否有与 C++11 emplace/emplace_back 函数类似的 C# 函数?

    从 C 11 开始 可以写类似的东西 include
  • 为什么 std::allocator 在 C++17 中丢失成员类型/函数?

    一边看着std 分配器 http en cppreference com w cpp memory allocator 我看到成员 value type pointer const pointer reference const refer
  • 范围和临时初始化列表

    我试图将我认为是纯右值的内容传递到范围适配器闭包对象中 除非我将名称绑定到初始值设定项列表并使其成为左值 否则它不会编译 这里发生了什么 include
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • 是否有一个 C++ 库可以从 PDF 文件中提取文本,例如 PDFBox for Java? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 去年 我使用 PDFBox 在 Java 中创建了一个应用程序来获取某些 PDF 文件中的原始文本 现在
  • 为什么我使用google'smtp'无法发送电子邮件?

    我有以下程序使用 smtp gmail com 587 发送电子邮件 namespace TestMailServer class Program static void Main string args MailMessage mail
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include

随机推荐

  • W3C 验证器无法处理 RDF/XML

    我正在尝试描述一个非常基本的地铁火车站地图 其中包含站点和时间 这个 RDF 到 Turtle 转换器 http rdf translator appspot com 可以解析我的 XML 但 W3C 验证器抛出 Error Your do
  • 在 R 中快速计算 > 10^6 余弦向量相似度

    我得到了约 1600 个文档 x 约 120 个单词的文档术语矩阵 我想计算所有这些向量之间的余弦相似度 但我们正在谈论约 1 300 000 次比较 n n 1 2 我使用了 parallel mclapply 和 8 但它仍然需要很长时
  • 我什么时候应该在 ColdFusion 中使用#?

    这是教授新人 ColdFusion 的最大障碍之一 何时使用 充其量是不明确的 由于使用它们通常不会产生问题 因此大多数人似乎倾向于过度使用它们 那么 基本规则是什么 我认为说哪里不使用 可能更容易 唯一的地方是在 cfif 语句和 cfs
  • MySQLClient 无法在装有最新版本 Big Sur 的 Macbook Pro M1 上通过 pip 安装

    在确保自制软件可以在其上运行后 我刚刚购买了一台带有 M1 芯片的新 Macbook Pro 我可以 pip 安装除 mysqlclient 之外的任何其他库 并且通过自制程序安装它没有问题 所以我想从下面的错误消息中看出 这是 mysql
  • 通过 HTTP 替代方案访问 JMX

    我们使用 MX4J 通过容器本身的 Web 界面访问 JMX 相关操作 属性 我想知道是否有可用的替代方案 因为 MX4J 的最后一个服务版本是在 2006 年 我基本上希望克服 MX4J 在处理集合方面的限制 I was 实验 http
  • 如何在 Linux 中以编程方式反转屏幕颜色

    例如 在 Ubuntu 中 您可以使用 Super M 反转屏幕颜色 需要桌面效果 请参阅 1 其他操作系统也有类似的功能 尽管我并不真正关心 Linux 以外的任何操作系统 如果我想编写一个在运行时反转屏幕颜色的简单程序 我应该考虑哪个
  • 如何将字符串中每个单词的第一个字母大写?

    s the brown fox 在这里做点什么 s应该 The Brown Fox 做到这一点最简单的方法是什么 The title http docs python org library stdtypes html str title字
  • VBS 脚本查找特定扩展名的所有文件并将它们复制到特定目的地

    我正在制作一个项目 通过创建一个脚本来在工作中使用来自动化我们的一个流程 我希望脚本检查用户名的输入 以搜索指定的用户配置文件路径中的任何 doc docx pdf pst 等文件 并将它们按原样复制到网络驱动器位置上创建的文件夹中 我的主
  • Grails 2抽象域继承问题

    当在 Grails 中使用抽象 或非抽象 继承时 以下内容对我不起作用 很快 我的继承如下 abstract BaseClass SomeClass extends BaseClass SomeOtherClass extends Base
  • Cordova iOS 启动 comgooglemaps 失败

    我有一个小问题 我使用 comgooglemaps 方案来调用谷歌地图并执行搜索 这工作正常 但问题是如果用户没有安装谷歌地图 现在 我如何检查这一点以及是否未安装谷歌地图以通过浏览器调用谷歌 或者调用用户使用的其他地图应用程序 Thanx
  • 使用 group_by(多个变量)时的 dplyr 问题

    我想开始使用 dplyr 代替 ddply 但我无法了解它是如何工作的 我已阅读文档 例如 为什么当我尝试 mutate 时 group by 函数无法按预期工作 看看mtcar 图书馆 车 假设我制作了一个 data frame 它是 m
  • UITableview 中的 UItextView,自动更正气泡不可见

    我有一个带有自定义单元格的 UITableView 每个单元格包含一个 UITextView 并且当用户在 TextView 中键入文本时 单元格会调整大小 我的问题是 当用户位于 TextView 自动更正第一行时 当前单元格中将看不到气
  • 将 HTML 类/ID 添加到 Google 地图标记 (API V3)

    如何向 Google Maps API V3 标记添加类或 ID 我希望能够使用 jQuery 访问标记 编辑 嗨 clarkf 感谢您的回复 使用 Firebug 在检查我的地图时我无法看到这些类 但我确实注意到有两个 div 一种用于图
  • 在页面重新加载时传递 $_GET 参数[重复]

    这个问题在这里已经有答案了 我试图做到这一点 以便当页面重新加载时 它使用与上一页相同的 GET 参数来重定向我 现在我正在尝试使用标头来实现此目的 但是当我提交表单时 变量 id 为空 HTML 表单
  • 为什么 Elastic Load Balancing 报告“停止服务”?

    我正在尝试设置弹性负载均衡 ELB http aws amazon com elasticloadbalancing 在AWS中用于在多个实例之间拆分请求 我基于相同的 AMI 创建了多个网络服务器镜像 并且我能够单独 ssh 进入每个镜像
  • Windows 批处理 FOR 命令制表符分隔符

    我正在尝试使用 Windows 批处理FOR命令 http www microsoft com resources documentation windows xp all proddocs en us for mspx mfr true
  • 使用 junit @Rule、expectCause() 和 hamcrest 匹配器

    我有一个测试 Rule public ExpectedException thrown ExpectedException none Test public void testMethod final String error error
  • PyQt 的 QMainWindow closeEvent 从未被调用

    我在 python 中使用 pyqt4 当我关闭 QMainWindow 窗口时 它不被处理closeEvent方法 请有人告诉我这段代码有什么问题 from PyQt4 import QtCore QtGui class Ui MainW
  • 未找到节点检查器命令

    我尝试安装并运行node inspector使用一堆不同的命令仍然无法运行它 Jordans MacBook Pro angular express blog jordanbaucke node inspector bash node in
  • 为什么 Blazor 生命周期方法会执行两次?

    因此 随着 asp net core 3 0 和 blazor 1 0 的发布 我开始使用 blazor 进行一些实际工作 将 Blazor 组件代码拆分为后台代码时 我使用以下内容 public class LogoutModel Bla