Blazor —— 深入讲解组件的生命周期

    技术2022-07-10  178

    目录

    前言关于 ComponentBase生命周期SetParameterAsyncOnInitialized / OnInitializedAsyncOnParametersSet / OnParametersSetAsyncOnAfterRender / OnAfterRenderAsyncStateHasChangedDispose 总结

    前言

    当我们学会写一些组件以后,就需要来了解一下一个组件从加载到渲染的整个生命周期,以此来知道我们可以在什么点对组件进行优化。

    关于 ComponentBase

    这是所有组件的基类,这是一个抽象类。一般情况下,组件需要继承这个基类。

    下面是 ComponentBase 的内容:

    生命周期

    Blazor 组件定义了一系列的虚方法,这样我们可以根据需要来重写里面的逻辑,以便处理我们自己的逻辑。

    我们通过一张图能更直观的看到他们的运行顺序:

    SetParameterAsync

    这个方法在组件运行后执行。参数们,也就是被标记了 Parameter 特性的参数在被设置以后,通过该方法的 ParameterView 参数传入进来。但是,标记了 [Parameter] 的参数这时还未得到从外面组件的赋值的结果。

    示例代码:

    [Parameter] public int Count { get; set; } public override async Task SetParametersAsync(ParameterView parameters) { Console.WriteLine("Count的值是:{0}", Count); var value= parameters.GetValueOrDefault<int>(nameof(Count)); Console.WriteLine("value的值是:{0}", value); await base.SetParametersAsync(parameters); } <Lifecycle Count="10"/>

    这个时候的 Count 参数的值是处于未被赋值的状态。因此,通过 parameters.GetValueOrDefault 来获取某一个参数的值。

    OnInitialized / OnInitializedAsync

    没有 Async 后缀的是异步方法,但结果都是一样的。但是执行顺序是:OnInitialized -> OnIntializedAsync

    当经过了刚才的 SetParametersAsync 方法之后,就会立即执行这个方法,表示组件已经初始化完成。这里我们可以得到所有的被标记过 [Parameter] 参数的值。

    Tips:这个时候界面是还没有开始被渲染,界面是空白状态,浏览器会有一个旋转图标,表示加载中,所以尽量避免在这一步编写长时间操作的代码,比如查询数据库,或者请求别的服务。

    当页面通过超链接对本页面的组件进行跳转,则不会执行 OnInitialized 方法:

    OnParametersSet / OnParametersSetAsync

    执行顺序依然是先同步后异步,即 OnParametersSet -> OnParametersSetAsync 。

    这是组件生命周期中可能被重复调用的第一对方法。如果组件的[参数]属性都没有改变,那么组件将简单地闲置,直到它最终被销毁。但是,如果其父HTML标记中的任何参数被更改,那么这些方法将在组件状态更新后触发。这将导致 Blazor 重新计算组件的渲染树,然后执行 OnAfterRender和OnAfterRenderAsync 方法。

    同样地,和 OnInitialized 方法一样,如果是同一组页面的组件,则不会执行 OnParametersSet 方法。参见上面的例子。

    举个例子:

    <Lifecycle Count="10" Name="@Name"/> <input type="text" @bind-value="Name" /> <br /> @Name @code{ public string Name { get; set; } }

    父组件的 Name 是一个被文本框进行双向绑定的变量,却又给组件的 Name 参数进行了赋值,因此当文本框进行了改变后,Name 变量发生了变化,因此被组件赋值的 Name 参数也发生了变化,然后 OnParametersSet 方法被执行了。

    OnAfterRender / OnAfterRenderAsync

    执行顺序为 OnAfterRender -> OnAfterRenderAsync。

    该方法会在渲染树工作完成后执行,即页面渲染结束。但该方法被执行一般会有以下情况:

    组件的[Parameter] 属性在父组件的HTML标记中被改变用户与组件进行了交互(例如鼠标点击)组件执行它的 StateHasChanged 方法来调用一个重新呈现。

    该方法会有一个布尔值参数 firstRender,该参数只有在方法第一次在当前组件上被调用时才为 true,此后它将始终为 false。

    为了演示,我增加了一个按钮功能。

    StateHasChanged

    此方法不符合生命周期方法的资格,但它确实触发了组件生命周期中的另一个方法。在默认情况下,Blazor会检查它的状态是否在某些交互之后发生了改变(比如点击按钮)。

    有时 Blazor 无法意识到状态的变化,例如何时被计时器触发。这时你需要手动调用 StateHasChanged 来通知 Blazor 某些参数已经被更改。表示向 Blazor渲染请求一个重新渲染,然后将触发 OnAfterRender 和OnAfterRenderAsync。

    Dispose

    尽管严格来说这不是 ComponentBase 的生命周期方法之一,但如果一个组件实现了 IDisposable,那么 Blazor 将在组件从父组件的呈现树中移除后执行Dispose 方法。

    要实现 IDisposable,我们需要在 razor 文件中添加 @implements IDisposable。

    @implements IDisposable <h1>一个销毁组件</h1> @code { void IDisposable.Dispose() { // Code here } }

    总结

    这一次我们对组件的生命周期有了更深一层次的理解,这对我们编写组件时非常有帮助的,不仅可以加强组件渲染的效率,同时也对于组件报错后的原因有了更进一步的排查方法。

    Processed: 0.013, SQL: 9