我很难理解何时应该调用StateHasChanged()以及何时 Blazor 拦截某些内容已更改,因此必须重新呈现。
我创建了一个示例项目,其中包含一个按钮和一个名为 AddItem 的自定义组件。该组件包含一个带有红色边框的 div 和一个按钮。
我所期望的:我希望当用户单击 Index 页面中包含的按钮时,AddItem 的 div 将显示出来。然后我想在用户单击 AddItem 的按钮时隐藏它。
注意: AddItem 不会将它的_isVisible标志暴露在外面,而是包含一个Show()方法。SoAddItems.Show()将在单击索引按钮时调用。
测试:
我点击索引的点击按钮,然后调用方法Open()和AddItem.Show()。标志_isVisible被设置为true但没有任何反应并且索引ShouldRender()被调用。
控制台输出:
我AddItem.Show()用public void Show() {_isVisible = true; StateHasChanged();}. 现在 AddItem 的 div 按预期显示和隐藏。
控制台输出:
我已经修改<AddItem @ref="AddItem" />了<AddItem @ref="AddItem" CloseEventCallback="CallBack" />,StateHasChanged从 AddItem 的Show()方法中删除。现在 AddItem 的 div 按预期显示和隐藏。
基于测试 3:为什么我不必明确
StateHasChanged将 AddItem 设置CloseEventCallback为任何父级的方法?我很难理解它,因为 AddItem 不会CloseEventCallback在任何地方调用。
和
当 Blazor 了解某些内容已更改,因此必须重新渲染时?
我的示例代码(如果你想尝试的话)。
我的 Index.razor
<AddItem @ref="AddItem" />
<button @onclick="Open">click</button>
@code {
AddItem AddItem;
public void Open()
{
AddItem.Show();
}
public void CallBack()
{
}
protected override bool ShouldRender()
{
Console.WriteLine("Render INDEX");
return base.ShouldRender();
}
}
Run Code Online (Sandbox Code Playgroud)
我的 AddItem 组件
@if (_visible)
{
<div style="width: 100px; height: 100px; border: 1px solid red">testo</div>
<button @onclick="Close">close</button>
}
@code {
private bool _visible = false;
[Parameter] public EventCallback<bool> CloseEventCallback { get; set; }
public void Show()
{
_visible = true;
}
public void Close()
{
_visible = false;
}
protected override bool ShouldRender()
{
Console.WriteLine("Render ADDITEM");
return base.ShouldRender();
}
}
Run Code Online (Sandbox Code Playgroud)
Isa*_*aac 18
一般来说,触发UI事件后会自动调用StateHasChanged()方法,比如点击按钮元素后,会引发click事件,会自动调用StateHasChanged()方法通知组件它的状态已经改变,它应该重新渲染。
最初访问 Index 组件时。父组件先渲染,然后父组件渲染子组件。
每当单击“打开”按钮时,索引组件都会重新渲染(这是因为事件的目标是父组件,默认情况下会重新渲染(无需使用 StateHasChanged)。但不是子组件,谁是不知道他的状态发生了变化。为了让孩子知道他的状态发生了变化并且应该重新渲染,您应该在 Show 方法中手动添加对 StateHasChanged 方法的调用。现在,当您单击“打开”按钮,先重新渲染子组件,然后再重新渲染其父组件。现在红色的div是可见的。
单击“关闭”按钮隐藏红色 div。这次只有子组件重新渲染(这是因为事件的目标是子组件,默认情况下它会重新渲染),而不是父组件。
这种行为是正确的并且是设计使然。
如果从 AddItem.Show 方法中删除对 StateHasChanged 方法的调用,定义此属性:[Parameter] public EventCallback<bool> CloseEventCallback { get; set; },并在父组件中添加一个组件属性,以便为该属性赋值,如下所示:
<AddItem @ref="AddItem" CloseEventCallback="CallBack" />,您会注意到外部没有变化,但是这次单击“打开”按钮时重新渲染的顺序是先父重新渲染,然后子重新渲染。这准确地描述了您在评论中发现的问题:
那么,为什么即使没有在任何地方调用 CloseEventCallback,我的测试 3 仍能按预期工作?
你是对的......在进一步调查之前,我无法真正解释这种行为。我会试着找出发生了什么,然后让你知道。
AddItem 的 close 方法调用 CloseEventCallback 来通知父级它应该重新呈现。
注意:您的代码使用布尔类型说明符定义 CloseEventCallback,因此您必须在具有布尔参数的父组件中定义一个方法。当您调用 CloseEventCallback 'delegate' 时,您实际上是在调用 Index.Callback 方法,您应该向它传递一个布尔值。自然地,如果您将值传递给组件,您希望它重新渲染,以便可以在 UI 中看到新状态。这就是 EventCallback 提供的功能:虽然事件是在子组件中触发的,但它的目标是父组件,这会导致父组件重新渲染。
我想知道如果调用了订阅的 EventCallback 之一,为什么父组件应该重新呈现自身?
这正是我在上面的段落中试图解释的。EventCallback 类型是专门为解决事件目标的问题而设计的,将事件路由到状态发生变化的组件(父组件),并重新渲染它。
小智 10
当父组件首次将组件添加到组件层次结构时,组件必须进行渲染。这是组件必须渲染的唯一一次。组件可以根据自己的逻辑和约定在其他时间呈现。
SPA 应用程序遵循以下组件架构:
将该树中的每个节点视为 Blazor 应用程序中我们的组件。该组件有一个父组件,并且可以有子组件。
ComponentBase(任何 Blazor 组件的标准基类)接收对 StateHasChanged 的调用。这是包含在以下时间自动触发重新渲染的逻辑的逻辑:
与 Blazor 的自动渲染调用不同,在我们的示例中,渲染调用来自 StateHasChanged。这具有不同的行为:
当框架本身在上述时间之一进行渲染时,它仅渲染其子组件(子组件)。
但是,当我们调用 StateHasChanged 时,大多数从 ComponentBase 继承的组件都会被渲染,无论它们在树中的位置如何。(不必要的重新渲染)。
因此,我们应该避免使用StateHasChanged,让框架来处理渲染。
调用 StateHasChanged 有意义的场合:
了解更多:
| 归档时间: |
|
| 查看次数: |
12966 次 |
| 最近记录: |