Blazor 中的 StateHasChanged 目标
Posted
技术标签:
【中文标题】Blazor 中的 StateHasChanged 目标【英文标题】:StateHasChanged goal in Blazor 【发布时间】:2020-08-11 02:25:54 【问题描述】:看看这个非常基本的组件:
<div>
@param1
<button @onclick="@btn_on_click">Cliquez là</button>
</div>
@code
[Parameter]
public int param1 get; set;
[Parameter]
public Action<int> on_evt_test_fire get; set;
void btn_on_click()
param1 += 1;
this.on_evt_test_fire(param1);
看看这个非常基本的页面:
@message
<button @onclick="@on_btn_click">Click me</button>
<MyComponent param1="1" on_evt_test_fire="@on_evt" />
<MyComponent param1="2" on_evt_test_fire="@on_evt" />
@code
private String message = "";
private void on_evt(int param_evt)
message = "Button clicked inside component";
StateHasChanged();
private async Task on_btn_click()
message = "Button clicked in this page";
我对 StateHasChanged() 有疑问。
我的第一个问题是:为什么我应该在 on_evt 中调用 StateHasChanged 而在 on_btn_click 中却没有必要。这两种方法之间的唯一区别是第一种是从组件内部调用的。在这种特定情况下,我为什么要调用 StateHasChanged ?
当我调用 StateHasChanged() 时,这 2 个组件被重置:它们取初始值...
感谢您的帮助
【问题讨论】:
【参考方案1】:而在 on_btn_click 中则不需要
on_btn_click 不需要,因为 UI 事件会自动调用 StateHasChanged 方法。
[Parameter]
public Action<int> on_evt_test_fire get; set;
您不应该使用 Action 委托。请改用 EventCallback 'delegate',如下所示:
注意:当你使用Action委托时,事件的目标是当前组件(子组件),而当你使用EventCallback时,目标是父组件,这就是为什么你不需要添加调用到 StateHasChanged 方法。在发现 EventCallback 之前,我们必须调用 StateHasChanged 方法。很久以前的事了……
[Parameter]
public EventCallback<int> on_evt_test_fire get; set;
你应该这样称呼它:
public async Task btn_on_click()
if( on_evt_test_fire.HasDelegate)
temp++;
await on_evt_test_fire.InvokeAsync(temp);
您不应使用 param1 参数来增加其值。定义 一个新变量,并为其分配了 param1 中的值 OnInitialized 方法如 这个:
protected override void OnInitialized()
temp = param1;
当我调用 StateHasChanged() 时,这两个组件被重置:它们取初始值..
--
不要创建写入自己的参数属性的组件 在以下情况下会覆盖参数:
子组件的内容使用 RenderFragment 呈现。
StateHasChanged 在父组件中被调用。 参数被重置,因为在调用 StateHasChanged 并且向子组件提供新参数值时父组件会重新呈现。
Source here:
See more here:
【讨论】:
我不同意:在 UI 事件上不会自动调用 StateHasChanged。这不是 StateHasChanged,因为我没有得到相同的结果/行为 “我不同意:在 UI 事件上不会自动调用 StateHasChanged”当然可以。您能否向我展示一个不调用 StateHasChanged 就无法工作的 UI 事件处理程序。 “这不是 StateHasChanged,因为我没有得到相同的结果/行为”不确定您的意思? 我偶然发现了这个讨论,因为实际上我面临着类似的情况。所以我发现,如果回调没有在组件上设置值,那么它并没有重新渲染我的组件。因此,我正在检查 EventCallback 的HasDelegate
属性,如果它为假,我将自己调用 StateHasChanged
。这通常对我有所帮助,但我不确定这是否是解决此问题的最佳方法。【参考方案2】:
我相信@onClick 回调会由于某些隐藏的逻辑而强制子重新渲染。当分配给按钮的 @onClick 时,您的回调或事件很可能被添加到 onClick 在内部执行的操作列表中。对此持保留态度,这只是我的理论。
编辑:您的参数被重置是因为 setState() 迫使您的父母使用硬编码的“1”和“2”从头开始重新渲染。当 onbuttonclicked 事件触发时,我相信它会在组件内部设置状态,从而保留数据。多加点盐。
【讨论】:
有没有办法在不重新初始化我的 2 个组件实例的情况下刷新“消息”变量显示? 尝试在“myComponent”中设置状态,这将重新渲染组件而不会丢失数据。如果你将状态设置为父级,你将丢失数据。【参考方案3】:@Henk 和@SilenceAmongCrows 的答案都是正确的。要添加的另一件事是,在您的子组件中,如果您使用 EventCallBack<T>
而不是 Action<T>
并将子组件中的 param1
属性绑定到父组件的 @code 块中的属性,则 Blazor引擎会更好地跟踪刷新什么以及何时刷新。
【讨论】:
以上是关于Blazor 中的 StateHasChanged 目标的主要内容,如果未能解决你的问题,请参考以下文章
何时在 Blazor 组件中调用 StateHasChanged()
Blazor 组件在 StateHasChanged() 之后未更新
我应该何时调用 StateHasChanged 以及 Blazor 何时自动拦截某些更改?