针对特定组件的StateHasChanged而是重新呈现页面中的所有组件

时间:2020-07-20 13:51:13

标签: 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;
    }
}

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

1 个答案:

答案 0 :(得分:1)

您可能不必担心组件渲染很多次。渲染仅构建一个渲染树,它不会更新浏览器的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);
}

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

@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);
  }
}

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

injectedState.Counter1++;
injectedState.Counter2--;
injectedState.NotifyChanged();