当 ShouldRender 被覆盖时,在每个 child 上单独调用 StateHasChanged

Calling StateHasChanged on each child individually when ShouldRender is overrriden

鉴于我有一堆 child 组件

<Parent>
   <Child ref="children[0]" />
   <Child ref="children[1]"/>
   <Child ref="children[2]" />
</Parent>

然后

与在 parent 组件上调用 StateHasChanged 相比,在每个 Child 组件上单独调用 StateHasChanged 是否有任何性能差异或副作用?

简单的回答:使用什么策略并不重要,只有虚拟 DOM 和 RenderTree 之间的差异被传递给实际 DOM。其他一切都只是执行代码。

一个更完整但更复杂的答案:

首先了解一下IComponentComponentBase的区别。所有组件都必须实现 IComponent - 这是 Renderer 用来与组件通信的接口。 ComponentBaseIComponent 的 Blazor 实现,也是 Razor 组件的默认基础组件。

Razor 标记组件被预编译为 C# class。您可以在 obj 目录中看到它们。

你的组件第一次被父组件传递给 Renderer 时:

  1. 像任何标准 C# 对象一样进行实例化。
  2. Renderer 将其添加到 RenderTree
  3. Renderer 调用 Attach 并传递它存储的组件 RenderHandle
  4. Renderer 调用 OnParametersSet 传递任何请求的参数。

就是这样,由 IComponent 定义。对于任何继承自 ComponentBase 的组件,众所周知的标准事件序列由 OnParametersSet 启动,包括调用 StateHasChanged.

StateHasChanged 是一种 ComponentBase 方法。它调用 RenderHandle.Render 传递代表组件的 RenderFragmentRenderFragment 中的任何新组件都会经历上述循环。对于任何现有组件,渲染器:

  1. 检查组件是否有任何子组件 - 这些可能有级联参数。
  2. 检查是否有任何组件的 Parameters 发生了变化。对于基元来说这很容易,但如果有任何对象,它会假定它们已经改变。

如果其中一个为真,它会在组件上调用 OnParametersSet 并传入适当的参数。

RenderHandle.RenderRenderFragment 堆叠在渲染队列中。执行时,队列更新渲染器持有的虚拟 DOM,然后运行 ​​Diffing 引擎以发现并将任何 DOM 差异传递给客户端,客户端更新浏览器中的实际 DOM。

我尽量保持简洁,但是......希望这有助于理解组件和渲染过程。