Blazor University (12)组件 — 组件生命周期

原文链接:https://blazor-university.com/components/component-lifecycles/

组件生命周期

源代码[1]

Blazor 组件具有许多我们可以重写以影响应用程序行为的虚拟方法。这些方法在组件生命周期的不同时间执行。下图概述了这些生命周期方法的流程。

组件生命周期图

e1a9b685b716c622986f3920fa927039.png

SetParametersAsync

每当父级渲染时执行此方法。

传递给组件的参数包含在 ParameterView 中。这是基于传递给组件的状态对服务器(举例)进行异步调用的好时机。

当您在重写中调用 base.SetParametersAsync(parameters) 时,将为组件的 [Parameter] 属性分配它们的值。

这也是分配默认参数值的正确位置。有关完整说明,请参阅可选路由参数[2]

OnInitialized / OnInitializedAsync

一旦 ParameterCollection 的状态被分配给组件的 [Parameter] 属性,这些方法就会被执行。这与 SetParametersAsync 一样有用,但可以使用组件的状态。

该方法仅在组件首次创建时执行一次。如果父级稍后更改组件的参数,则跳过此方法。

注意: 当组件是 一个 @page,并且我们的 Blazor 应用导航到渲染同一页面的新 URL 时,Blazor 将重用该页面的当前对象实例。因为对象是同一个实例,所以 Blazor 不会在对象上调用 IDisposable.Dispose,也不会再次执行其 OnInitialized 方法。

OnParametersSet / OnParametersSetAsync

如果这是组件的新实例,则此方法将在 OnInitializedAsync 之后立即执行。如果它是由于其父组件正在重新渲染而正在重新渲染的现有组件,则不会执行 OnInitialized 方法,而是在 SetParametersAsync 之后立即执行此方法。

StateHasChanged

此方法标记要渲染的组件。

每当组件想通知 Blazor 发生了会导致渲染输出不同的更改时,它都会调用此方法。例如,在 Clock 组件中,我们可能会设置一个循环 1 秒的计时器,然后执行 StateHasChanged 以便以正确的时间重新渲染。

另一个用途是指示 Blazor 通过异步方法部分执行重新渲染。

private async Task GetDataFromMultipleSourcesAsync()
{var remainingTasks = new HashSet<Task>(CreateTheTasks());while (remainingTasks.Any()){Task completedTask = await Task.WhenAny(remainingTasks);remainingTasks.Remove(completedTask);StateHasChanged();}
}

当等待发生时(第 6 行)或方法完成时(第 10 行),将处理对 StateHasChanged 的调用。

ShouldRender

该方法可以通过返回 false 来防止组件的渲染树被重新计算。请注意,第一次创建和渲染组件时不会执行此方法。

当我们知道我们的状态自上次渲染后未更改或仅以会导致渲染相同输出的方式更改时,指示 Blazor 不执行 BuildRenderTree 操作可以节省处理时间并改善用户体验。

第一次渲染组件时不执行此方法。

BuildRenderTree

此方法将组件的内容渲染为应渲染给用户的内存表示(RenderTree[3])。

<h1>People</h1>
@foreach(Person currentPerson in people)
{<ShowPersonDetails Person=@currentPerson/>
}

前面的标记将在渲染树中添加一个 h1,其中“People”作为其内容。然后它将为 people 中的每个 Person 创建一个 ShowPersonDetails 的新实例。

如果我们的组件稍后在 people 中使用附加项重新渲染,则将创建 ShowPersonDetails 组件的新实例并将其添加到我们组件的渲染树中。如果 people 中的项目较少,那么之前创建的一些 ShowPersonDetails 组件实例将从我们组件的渲染树中丢弃,如果它们实现 IDiposable,则会对它们执行 Dispose()

注意: 为了提高渲染效率,在任何类型的循环中渲染标记时,请尽可能始终使用 @key 指令[4]

OnAfterRender / OnAfterRenderAsync

每次 Blazor 重新生成组件的渲染树[5]时,都会执行最后两个方法。这可能是由于组件的父级重新渲染、用户与组件交互(例如鼠标单击)或组件执行其 StateHasChanged 方法来调用重新渲染的结果。

这些方法有一个名为 firstRender 的参数。此参数仅在当前组件上第一次调用该方法时为 true,从那里开始它将始终为 false。在需要附加组件连接的情况下(例如,通过 JavaScript),知道这是第一次渲染很有用。

直到 OnAfterRender 方法执行之后,才能安全地使用通过 @ref 指令设置的组件的任何引用。

<ChildComponent @ref=MyReferenceToChildComponent/>@code
{// This will be null until the OnAfterRender* methods executeChildComponent MyReferenceToChildComponent;
}

直到 OnAfterRender 方法被执行并且 firstRender 设置为 true 之后,使用通过 @ref 指令设置的 HTML 元素的任何引用是安全的。

<h1 @ref=MyReferenceToAnHtmlElement>Hello</h1>@code
{// This will be null until the OnAfterRender* methods execute// with firstRender set to trueElementReference MyReferenceToAnHtmlElement;
}

Dispose

尽管这并不是 ComponentBase 的生命周期方法之一,但如果组件实现了 IDisposable,那么一旦从其父级的渲染树中删除该组件,Blazor 就会执行 Dispose。要实现 IDisposable,我们需要将 @implements IDisposable 添加到我们的 razor 文件中。

@implements IDisposable
<h1>This is MyComponent</h1>@code {void IDisposable.Dispose(){// Code here}
}

在异步生命周期方法中等待

请务必注意,Blazor 不会在能够渲染组件之前等待长时间运行的异步方法完成,而是会尽快触发渲染。

这使组件能够在执行后台任务(例如从服务器检索数据)时渲染标记供用户查看。

SetParametersAsync

  • 第一次 await 的动作

    继续生命周期过程 (如果是新实例则为 OnInitialized,否则为 OnParametersSet

  • 退出方法的动作

    没有进一步的动作

注意: base.SetParametersAsync 方法必须在方法中的任何 await 指令之前执行,否则会抛出 InvalidOperationException

OnInitializedAsync

  • 第一次 await 的动作

    渲染组件

  • 退出方法的动作

    继续生命周期过程

OnParametersSetAsync

  • 第一次 await 的动作

    渲染组件

  • 退出方法的动作

    继续生命周期过程

OnAfterRenderAsync

  • 第一次 await 的动作

    没有进一步的动作

  • 退出方法的动作

    没有进一步的动作

简单的规则是 SetParametersAsync 是唯一不能通过等待任务来暂停生命周期过程的方法。

所有其他异步方法都可以暂停生命周期过程,直到执行退出该方法,并且第一个 await 将通过 BuildRenderTree 进行渲染,以防止用户不得不等待查看更新。

OnAfterRenderAsync 可能看起来像一个异常,因为它在任何一种情况下都不会执行进一步的操作。如果我们考虑渲染是执行链的末端这一事实,那么我们可以将其视为完成链而不是什么都不做。至于等待渲染,如果需要,程序员必须通过调用 StateHasChanged 显式完成,否则 OnAfterRenderAsync 中的等待将导致无限循环。

具有异步等待的组件生命周期

48d687091a40638861fff4fc3d9479ce.png

异步方法和多个等待

Blazor 在异步方法中的 await 上执行的代码只会在第一次 await 时执行。后续等待不会导致多次渲染。例如

protected override async Task OnParametersSetAsync()
{// Automatically renders when next line starts to awaitawait Task.Delay(1000); // No automatic render when next line starts to awaitawait Task.Delay(1000); // No automatic render when next line starts to awaitawait Task.Delay(1000); 
}

如果我们想在其他点进行渲染,那么我们必须在所有其他 await 语句之前调用 StateHasChanged

protected override async Task OnParametersSetAsync()
{// Automatically renders when next line starts to awaitawait Task.Delay(1000); // Explicitly render when next line starts to awaitStateHasChanged();await Task.Delay(1000); // Explicitly render when next line starts to awaitStateHasChanged();await Task.Delay(1000); 
}

有关如何安全地使用在同一组件上运行的不同线程的更多信息,请参阅多线程渲染[6]部分。

参考资料

[1]

源代码: https://github.com/mrpmorris/blazor-university/tree/master/src/Components/ComponentLifecycles

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何通过css控制内容显示顺序 第二行的内容优先显示

我们有时进行网页设计时为了想让用户感兴趣的内容优先显示在前&#xff0c;又不想改动代码的先后顺序&#xff0c;要怎么操作呢&#xff1f;&#xff08;或者换种说法&#xff1a;源代码中要先看到A再看到B&#xff0c;而视觉上是先B再A&#xff09;举个简单的例子&#xff0c;…

【C语言简单说】十七:数组(补)

上一节 我们所说的数组是整数类型的对吧&#xff1f;那么我们还有其他类型 的数组&#xff0c;在这里用字符数组举例。 如下代码&#xff1a; #include<stdio.h> #include<stdlib.h> int main() {char a[5]{a,b,c,d,e};int i;for(i0;i<5;i){printf("a[%d…

WireShark之抓包过滤链接部分

1 问题 我们打开WireShark&#xff0c;开始抓包&#xff0c;然后浏览器输入http链接地址&#xff0c;那我们怎么快速在WireShark里面找到 2 解决办法 1&#xff09;在WireShark里面输入http 2 ) Ctrl F,然后选择字符串&#xff0c;然后在字符串的右边输入 我们要过滤的部分…

最通俗易懂的依赖注入之生命周期

这篇文章是 ASP.NET 6 依赖注入系列文章的第二篇&#xff0c;点击上方蓝字可以阅读整个系列。在上一篇文章中&#xff0c;我们讨论了什么是依赖注入和控制反转&#xff0c;以及它的作用是什么。在这篇文章中&#xff0c;我们先演示一下依赖注入的基本用法&#xff0c; 然后再讨…

Cnblogs自定义皮肤css样式-星空观测者

不知不觉来Cnblogs也这么久了&#xff0c;然而Blogs提供的主题还是依旧那么复古&#xff0c;总觉得阅读起来难免枯燥&#xff0c;虽然我认为做技术不可以太过浮躁&#xff0c;但是一个美观的主题终究是吸引人眼的第一要素。 毕竟这么久了&#xff0c;在博客园还没有发现一个比较…

我的世界java版forge怎么用_我的世界电脑版MOD怎么用 我的世界pc版forge怎么安装...

我的世界由游戏本体以及启动器两部分组成&#xff0c;要玩游戏就要下载好本体再用启动器启动&#xff0c;单有游戏或者单有启动器都是玩不成的&#xff0c;想知道我的世界电脑版怎么开始&#xff0c;我的世界pc版启动器怎么用就来看看吧&#xff01;▍MOD怎么用1.安装MOD前要先…

【C语言简单说】十八:二维数组

这里可能会让大家脑袋迷糊&#xff0c;不过没事&#xff0c;多动动脑。 这一节我们来说二维数组&#xff0c;啥叫二维数组&#xff1f;之前我们那个是一维数组&#xff0c;好了&#xff0c;我们接下来大家就会慢慢的搞懂的。 我们的一维数组就像 一列排得整整齐齐的队伍&…

应用系统日志采集解决方案

概述 基于Flume MongoDB&#xff0c;对现有的多个应用系统进行日志采集。特点 采集范围每一次用户请求的请求信息。数据量大尽量减少现有系统的改动数据流图 说明&#xff1a;首先考虑的结构体系&#xff0c;是直接在应用系统中&#xff0c;将日志数据写到Flume&#xff1b;但…

每个程序员都可能犯过的10个错误

1. 面向编译器写代码&#xff0c;而不是面向用户 当人们使用编译器创建自己的 app 时&#xff0c;在把自己的想法诉诸于机器代码的过程中&#xff0c;常常会将那些可以使得编程更为简单却又冗长的语法遗忘于脑后。 无论你使用的是单字母的标识符还是更易于人脑理解的标识符&…

Xamarin效果第二十二篇之录音效果

在前面文章中简单玩了玩GIS的基本操作、Mark相关、AR、测距、加载三维白模和可扩展浮动操作;今天抽空再来分享一下录音效果;啥也不说了都在效果里:1、首次尝试了开源的Plugin.AudioRecorder结果发现没效果,也可能是我的姿势不对:https://github.com/NateRickard/Plugin.AudioRe…

从零开始来看一下Java泛型的设计

引言 泛型是Java中一个非常重要的知识点&#xff0c;在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java泛型的设计&#xff0c;将会涉及到通配符处理&#xff0c;以及让人苦恼的类型擦除。 泛型基础 泛型类 我们首先定义一个简单的Box类&#xff1a; public c…

php json error,PHP 7.3 中的 JSON 错误处理

PHP 7.3 为 json_encode() 和 json_decode() 函数增加的一个新特性使其更好的处理错误。这个特性「 RFC 」以 23 比 0 的投票结果被一致接受。让我们看一看在 PHP 7.2 及一下版本中是如何处理 JSON 错误的&#xff0c;以及 PHP 7.3 中新的改进。背景当前在 PHP7.2 版本中&#…

【C语言简单说】十九:二维数组循环嵌套(2)

这节直接用循环嵌套来输出二维数组了&#xff1a; 注&#xff1a;我说的队和列并不是一般说法&#xff0c;我用此比喻好让新手更好理解。 #include<stdio.h> #include<stdlib.h> int main() {int array[2][3]{1,2,3,4,5,6};//第一句 int i,j;//第二句 for(i0;i&l…

lia人是什么意思_狗狗喜欢舔人到底什么意思?毛孩的心思主人你要懂

很多人都喜欢养狗&#xff0c;因为它们忠诚、淘气、可爱。同时&#xff0c;狗狗也有很多奇怪的习惯&#xff0c;例如&#xff1a;喜欢舔人&#xff0c;喜欢追逐活动的东西等等。不过大多数狗主人通常都会有一个最想知道的问题&#xff1a;为什么狗狗总喜欢舔人&#xff0c;它们…

“爱思助手”曝为iOS木马:可绕过苹果DRM机制

一款新的iOS木马已在国内曝光&#xff0c;它可以通过PC感染未越狱的iOS设备&#xff0c;而无需利用企业证书。Palo Alto Networks指出&#xff0c;其名叫“爱思助手”(AceDeceiver)&#xff0c;目前正在影响我国的iOS用户。“爱思助手”利用了苹果数字版权管理(DRM)上的FairPla…

php运行条件,PHP配置环境要求 php运行的先决条件

类型&#xff1a;编程相关大小&#xff1a;320KB语言&#xff1a;中文 评分&#xff1a;6.6标签&#xff1a;立即下载在本教程中&#xff0c;假设用户的服务器已经安装并运行了 PHP&#xff0c;所有以 .php 结尾的文件都将由 PHP 来处理。在大部分的服务器上&#xff0c;这是 P…

【C语言简单说】二十:指针基础

。。据说指针很难 其实稍微理解概念不难。 先看百科的定义&#xff1a;在计算机科学中&#xff0c;指针&#xff08;Pointer&#xff09;是编程语言中的一个对象&#xff0c;利用地址&#xff0c;它的值直接指向&#xff08;points to&#xff09;存在电脑存储器中另一个地方的…

Javascript中的循环变量声明,到底应该放在哪儿?

不放走任何一个细节。相信很多Javascript开发者都在声明循环变量时犹 豫过var i到底应该放在哪里&#xff1a;放在不同的位置会对程序的运行产生怎样的影响&#xff1f;哪一种方式符合Javascript的语言规范&#xff1f;哪一种方式和ecma标准未来的发展 方向匹配&#xff1f;本文…

Delphi全局热键的注册

1.在窗启动时创建ATOM;(aatom:ATOM;定义在private中&#xff09; 1 if FindAtom(ZWXhotKey)0 then 2 begin 3 aatom:GlobalAddAtom(ZWXhotKey); 4 end; 5 if RegisterHotKey(Handle,aatom,MOD_ALT,$41) then 6 begin 7 MessageBox(Handle,按alta,提示,MB_OK); 8 end; 2.定义处…

【C语言简单说】二十一:双重指针基础 (完结)

其实后面这两节我是用我几年前写的教程复制过来的。。。 ’ – ’ ) ( &#xff13; )╱~~ 如有错误&#xff0c;请留言提醒哈~~~尴尬的笑。 多重指针呢其实就是指向指针的指针。 首先&#xff0c;变量大家都知道是啥意思了吧&#xff1f;一个变量是有地址的。那么指针变量也是…