SetParameterAsync
这个方法在组件运行后执行。参数们,也就是被标记了 Parameter
特性的参数在被设置以后,通过该方法的 ParameterView
参数传入进来。但是,标记了 [Parameter]
的参数这时还未得到从外面组件的赋值的结果。
OnInitialized
/ OnInitializedAsync
没有
Async
后缀的是异步方法,但结果都是一样的。但是执行顺序是:OnInitialized
->OnIntializedAsync
当经过了刚才的 SetParametersAsync
方法之后,就会立即执行这个方法,表示组件已经初始化完成。这里我们可以得到所有的被标记过 [Parameter]
参数的值。
Tips:这个时候界面是还没有开始被渲染,界面是空白状态,浏览器会有一个旋转图标,表示加载中,所以尽量避免在这一步编写长时间操作的代码,比如查询数据库,或者请求别的服务。
当页面通过超链接对本页面的组件进行跳转,则不会执行 OnInitialized
方法
OnParametersSet
/ OnParametersSetAsync
执行顺序依然是先同步后异步,即
OnParametersSet
->OnParametersSetAsync
。
这是组件生命周期中可能被重复调用的第一对方法。如果组件的[参数]属性都没有改变,那么组件将简单地闲置,直到它最终被销毁。但是,如果其父HTML标记中的任何参数被更改,那么这些方法将在组件状态更新后触发。这将导致 Blazor 重新计算组件的渲染树,然后执行 OnAfterRender
和OnAfterRenderAsync
方法。
同样地,和 OnInitialized
方法一样,如果是同一组页面的组件,则不会执行 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
。
Blazor中的StateHasChanged()
与InvokeAsync(StateHasChanged)
我知道调用
StateHasChanged()
方法会通知组件状态已更改,它应该re-render
。然而,我也在其他人的代码中看到对
await InvokeAsync(StateHasChanged)
或await
InvokeAsync(() => StateHasChanged())
的调用,但我不太理解它与StateHasChanged()
的比较,以及什么时候应该优先于另一个,以及为什么。我能找到的唯一信息是Blazor文档的这一部分,上面写着:
在必须基于外部事件(如计时器或其他通知)更新组件的情况下,请使用
InvokeAsync
方法,该方法将分派到Blazor的同步上下文。我不太明白。它只是说"…which分派到Blazor的同步上下文”,但我对此不太满意!什么是“Blazor的同步上下文”?
我尝试过在
TimerElapsed
事件中调用StateHasChanged()
而不是InvokeAsync(StateHasChanged)
,它按预期工作,没有任何问题。我应该打电话给awaitInvokeAsync(StateHasChanged)
吗?!如果是,为什么呢?我觉得这里可能有一些我不知道的重要的细微差别。我也见过类似
InvokeAsync(() => InvokeAsync(Something))
的电话,为什么?另外,我有时也会看到
InvokeAsync()
没有await
被调用,这怎么办?!
在计时器的已用事件中调用StateHasChanged()
——而不是InvokeAsync(StateHasChanged)
,它按预期工作
那一定是在WebAssembly
上。在Blazor
服务器端尝试一下,我希望会出现一个异常。
核心问题是呈现和调用StateHasChanged
都必须在主(UI)thread
上进行。卷影DOM副本不是thread-safe
。
主Blazorlife-cycle
事件(OnInit、AfterRender、ButtonClick
)都是在这个特殊的thread
上执行的,因此在极少数需要StateHasChanged()
的情况下,可以不使用InvokeAsync()
调用它。
但是计时器不同,它是一个“外部事件”,因此您不能确定它将在正确的thread
上执行。InvokeAsync()
将工作委托给右边thread
(它属于Blazor
的同步上下文)。
但是blazorwebassembly
只有1个thread
,因此目前外部事件也在同步上下文中运行。这意味着当你做错事的时候你什么都不会注意到。直到有一天,当blazorwasm
最终实现threads
时,您的代码将失败。就像你的计时器实验一样。
什么是“Blazor的同步上下文”?
在.net中,同步上下文决定等待(之后)发生什么。不同的平台有不同的设置,Blazor
synccontext
非常类似于WinForms
和WPF
。主要是,默认值是.ConfigureAwait(true)
:在相同的thread
上恢复。
我有时在blazorwasm代码中看到.ConfigureAwait(false)
,当我们得到threads
时,它就会爆炸。
最后,await InvokeAsync(StateHasChanged)
或await InvokeAsync(() => StateHasChanged()
只是关于C中的lambda
,与Blazor
无关。第一个简短的形式更有效一些。
我有时也看到InvokeAsync()
没有await
调用
这绝不是一个好主意,尽管它通常会奏效。把它当作一个错误。
标签:生命周期,StateHasChanged,调用,InvokeAsync,组件,Blazor,方法 From: https://www.cnblogs.com/stonechina/p/17100939.html