考虑具有字符串参数和复杂类型参数的子组件。
<Child Name="@strProperty" />
<Child Model="@compelexType" />
假设两个参数都没有更改,那么在父组件上调用StateHasChanged会导致具有复杂参数的Child组件重新应答,但不会使用字符串参数。
请参阅此演示:https://blazorrepl.com/repl/wbYguGuA515uMYR742
你如何解释不同的行为?
这本身不是一个答案,我只是需要比注释中更多的空间。
我不相信引用的文件完全解释了观察到的结果。
文档说明:
默认情况下,Razor组件继承自ComponentBase基类,该基类包含在以下时间触发重新渲染的逻辑:
- 从父组件应用更新的参数集之后
- 为级联参数应用更新的值之后
- 在通知事件并调用其自己的事件处理程序之后
- 在调用其自己的StateHasChanged方法之后(请参阅ASP.NET Core Razor组件生命周期(
这些都是内部操作。前两个发生在对组件调用SetParametersAsync
之后。最后两个来自组件内部的操作。
任何子组件活动(如重新渲染(都是由调用SetParametersAsync
的Renderer
触发的,而不是由父组件直接触发的。CCD_ 4基于检测到的对任何子组件CCD_。因此,发生重新渲染的原因是Renderer
决定它是一个对象而不是基元类型,与ComponentBase
无关。
为了证明这一点,我基于IComponent
而不是ComponentBase
编写了一个非常基本的组件。它看起来像这样:
using Blazor.Starter.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System.Threading.Tasks;
namespace Blazor.Starter.Components.TestComponents
{
public class ObjectTest : IComponent
{
[Parameter] public DataModel Model { get; set; }
[Parameter] public int Value { get; set; }
private RenderHandle _renderHandle;
private int _renders;
public void Attach(RenderHandle renderHandle)
{
_renderHandle = renderHandle;
}
public Task SetParametersAsync(ParameterView parameters)
{
parameters.SetParameterProperties(this);
_renders++;
this.Render();
return Task.CompletedTask;
}
public void Render()
=> _renderHandle.Render(RenderComponent);
private void RenderComponent(RenderTreeBuilder builder)
{
builder.OpenElement(0, "div");
builder.AddContent(1, $"Rendered {_renders}");
builder.CloseElement();
}
}
}
如果在调用父级SetParametersAsync
时设置Model
,如果仅设置Value
,则不会。同样的结果。
文档:
如果以下任一项为真,则从
ComponentBase
继承的组件会由于参数更新而跳过转发器:
- 所有参数值都是已知的不可变的基元类型,如
int
、string
、DateTime
和自上一组参数设置以来没有更改- 组件的
ShouldRender
方法返回false
正如@GSerg在评论中所说:这是因为基元属性没有更改,所以它不会更新。