且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

我什么时候应该调用StateHasChanged,什么时候Blazor会自动截获某些更改?

更新时间:2022-12-08 11:00:31

通常来说,触发UI事件后会自动调用StateHasChanged()方法, 例如,在单击按钮元素之后,将引发click事件,并且StateHasChanged()方法为 自动调用以通知组件其状态已更改,并且应重新呈现.

Generally speaking, the StateHasChanged() method is automatically called after a UI event is triggered, as for instance, after clicking a button element, the click event is raised, and the StateHasChanged() method is automatically called to notify the component that its state has changed and it should re-render.

首次访问索引组件时.父组件先渲染,然后渲染父组件 呈现其子项.

When the Index component is initially accessed. The parent component renders first, and then the parent component renders its child.

每当单击打开"按钮时,索引组件就会重新呈现(这是因为 事件的目标是父组件,默认情况下它将重新渲染 (无需使用StateHasChanged).但不是那个不知道自己的孩子 状态已经改变.为了使孩子知道他的状态已经改变并且状态已经改变 应该重新渲染,您应该添加对StateHasChanged方法的调用 手动在Show方法中.现在,当您单击打开"按钮时,子组件为 首先重新渲染,然后其父级重新渲染.现在红色的div变为可见.

Whenever the "Open" button is clicked the Index component re-renders (This is because the target of the event is the parent component, which by default will re-render (No need to use StateHasChanged). But not the child, who is not aware that his state has changed. In order to make the child aware that his state has changed and that it should re-render, you should add a call to the StateHasChanged method manually in the Show method. Now, when you click on the "Open" button, the child component is re-rendered first, and then its parent re-renders next. Now the red div is rendered visible.

点击关闭"按钮以隐藏红色的div.这次只有子组件重新呈现 (这是因为事件的目标是子组件,并且默认情况下会重新呈现), 但不是父母.

Click the "Close" button to hide the red div. This time only the child component re-renders (This is because the target of the event is the child component, and it re-renders by default), but not the parent.

此行为是正确的,是设计使然.

This behavior is correct and by design.

如果从AddItem.Show方法中删除对StateHasChanged方法的调用,请定义此 属性:[Parameter] public EventCallback<bool> CloseEventCallback { get; set; },并添加 父组件中的一个组件属性,可以为该属性分配一个值,如下所示: <AddItem @ref="AddItem" CloseEventCallback="CallBack" />,您会发现外观没有变化, 但这一次单击打开"按钮时的重新渲染顺序是父级 重新渲染,然后孩子重新渲染.这恰好描述了您发现的问题 您在评论中提出的问题:

If you remove the call to the StateHasChanged method from the AddItem.Show method, define this property: [Parameter] public EventCallback<bool> CloseEventCallback { get; set; }, and add a component attribute in the parent component to assign a value to this property like this: <AddItem @ref="AddItem" CloseEventCallback="CallBack" />, you'll notice no change outwardly, but this time the order of re-rendering when the "Open" button is clicked, is first the parent re-renders, then the child re-renders. This describes exactly the issue you've found expressed in your question from the comments:

那么,为什么即使未在任何地方调用CloseEventCallback,我的测试3仍能按预期工作?

So, why my test 3 worked as expected even if CloseEventCallback isn't invoked anywhere?

您是对的...在进行进一步调查之前,我无法真正解释此行为. 我将尝试找出正在发生的事情,并告诉您.

You are right... I could not really explain this behvior before having a further investigation. I'll try to find out what is going on, and let you know.

AddItem的close方法调用CloseEventCallback来通知父级应重新呈现.

AddItem's close method invoke the CloseEventCallback to advise the parent that it should re-render.

注意:您的代码使用布尔类型说明符定义CloseEventCallback,因此您必须定义一个方法 在具有布尔参数的父组件中.当您调用CloseEventCallback'delegate'时 您实际上调用了Index.Callback方法,并且应该向其传递一个布尔值.当然,如果您通过 一个组件的值,您希望它重新呈现,以便可以在UI中看到新状态.这是 EventCallback提供的功能:尽管事件是在子组件中触发的, 它的目标是父组件,这将导致父组件重新呈现.

Note: your code define the CloseEventCallback with a boolean type specifier, so you must define a method in your parent component that has a boolean parameter. When you invoke the CloseEventCallback 'delegate' you actually call the Index.Callback method and you should pass it a boolean value. Naturally, if you passes a value to a component, you expect it to re-render so that the new state can be seen in the UI. And this is the functionality that the EventCallback provides: Though the event is triggered in the child component, its target is the parent component, which results in the parent component re-rendering.

我想知道如果订阅的EventCallback之一被调用,为什么父组件应该重新呈现自身?

I am wondering why a parent component should re-render itself if one of the subscribed EventCallback is invoked?

这正是我在上一段中要解释的内容. EventCallback类型是专门为解决事件目标的问题而设计的,将事件路由到组件 状态更改(父组件),然后重新呈现.

This is exactly what I'm trying to explain in the paragraph above. The EventCallback type was especially design to solve the issue of the event target, routing the event to the component whose state has changed (the parent component), and re-rendering it.