StateHasChanged 针对特定组件,而不是重新渲染页面中的所有组件

Kes*_*iam 6 c# blazor

我的应用程序使用多个组件,每个组件都以条件方式呈现。是否有可能单独重新渲染特定组件?

MyRazor.razor文件,

 <button @onclick="Chnage">Second</button>
<div>
    @if (renderOne)
    {
        var data1 = Count++;
        <ComponentFirst>@data1</ComponentFirst>
    }
    @if (renderTwo)
    {
        var data2 = Count2++;
        <ComponentSecond class="btn-danger">@data2</ComponentSecond>
     }
</div>
@code { 
    void Chnage()
    {
        renderOne = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

ComponentFirst 和 ComponentSecond 通过检查各自的布尔值来呈现。在单击按钮时,我单独启用了 CompoenentFirst。但 ComponentSecond 也再次渲染。我的目标是如果我启用 renderOne ComponentFirst 应该再次渲染。如果我禁用 renderTwo ComponentTwo 应该再次渲染,而不是为应用程序中的单个更改渲染两个组件。

Pet*_*ris 3

您可能不应该担心组件会多次渲染。渲染仅构建渲染树,它不会更新浏览器的 DOM。只有构建整个页面的渲染树后,Blazor 才会将其与最后一个渲染树进行比较,然后根据差异更新 DOM。

话说回来:

如果父组件通过属性[Parameter](包括RenderFragment)将任何信息传递给子组件,那么每当父组件重新渲染时,子组件也会重新渲染,以防万一发生任何更改。

如果您希望组件独立于其父组件重新渲染,那么您不应该将任何状态传递给它们。您可以通过在组件外部存储状态来实现这一点。例如

public class MyState
{
  public int Count1 { get; set; }
  public int Count2 { get; set; }

  public event EventHandler<EventArgs> Changed;
  public void NotifyChanged() => Changed?.Invoke(this, EventArgs.Empty);
}
Run Code Online (Sandbox Code Playgroud)

如果您将其注册为可注入依赖项,那么您可以直接在子组件中使用它

@inject MyState State
@implements IDisposable

<div>
  The value is @State.Count1
</div>

@code
{
  protected override void OnInitialized()
  {
    State.Changed += DoUpdate;
  }

  void IDisposable.Dispose()
  {
    State.Changed -= DoUpdate; // Important1
  }

  private void DoUpdate(object sender, EventArgs e)
  {
    InvokeAsync(StateHasChanged);
  }
}

Run Code Online (Sandbox Code Playgroud)

MyState任何组件都可以通过注入然后执行来更新状态

injectedState.Counter1++;
injectedState.Counter2--;
injectedState.NotifyChanged();
Run Code Online (Sandbox Code Playgroud)