当其他组件发生更改时,我需要更新 blazor 组件的状态

I need to update state of blazor component when other component changed

提问人:Alexan 提问时间:5/16/2023 更新时间:5/16/2023 访问量:457

问:

我有一个包含不同组件的 blazor 页面。

组件结构如下:

page
   component1
      component11
    component2

当 component11 上发生事件时,component2 应更新其状态。

在同一个组件上,我使用 event。OnStateChange

对于父组件的更新状态,我也可以使用 EventCallback。

但是在这里,我需要将事件向上传递两个级别,然后向下传递到其他组件。

看起来有点复杂。也许存在一些简单的方法来做到这一点。

事件冒泡可以自动工作吗?也许是一些应用程序设置?

net-6.0 blazor-server-side event-bubbling blazor-component

评论


答:

3赞 MrC aka Shaun Curtis 5/16/2023 #1

您需要使用某种形式的通知模式。

这是一个简单的提供程序。请注意,它需要从 DI 到 demo 注入服务。WeatherForecastService

public class TimeStampProvider
{
    private readonly WeatherForecastService _weatherForecastService;

    public TimeStampProvider(WeatherForecastService weatherForecastService)
        => _weatherForecastService = weatherForecastService;

    public event EventHandler? TimeStampChanged;

    public string TimeStamp = string.Empty;

    public void NotifyTimeStampChanged(string timeStamp)
    {
        TimeStamp = timeStamp;
        this.TimeStampChanged?.Invoke(this, EventArgs.Empty);
    }
}

您可以将其注册为作用域内的 DI 服务,或者,如果您在页面范围内使用它,请在页面组件中创建一个实例并级联它。

接下来是几个使用 .TimeStampProvider

TimeStampSetter

<div class="m-2 p-2">
    <button class="btn btn-primary" @onclick=this.Clicked>Update Time Stamp</button>
</div>

@code {
    [CascadingParameter] private TimeStampProvider myProvider { get; set; } = default!;

    protected override void OnInitialized()
    {
        ArgumentNullException.ThrowIfNull(this.myProvider);
    }
    private void Clicked()
        => myProvider.NotifyTimeStampChanged(DateTime.Now.ToLongTimeString());
}

时间戳查看器

@implements IDisposable
<div class="bg-dark text-white m-2 p-2">
    <pre>Stamp : @myProvider.TimeStamp </pre>
</div>

@code {
    [CascadingParameter] private TimeStampProvider myProvider { get; set; } = default!;

    protected override void OnInitialized()
    {
        ArgumentNullException.ThrowIfNull(this.myProvider);
        this.myProvider.TimeStampChanged += this.OnChanged;
    }
    private void OnChanged(object? sender, EventArgs e)
        => this.InvokeAsync(StateHasChanged);

    public void Dispose()
        => this.myProvider.TimeStampChanged -= this.OnChanged;
}

我的组件

<div class="bg-secondary m-3 p-2">
    <h3>MyComponent</h3>
    <TimeStampViewer />
    <TimeStampSetter />
</div>
@code {

}

最后是页面,有许多子组件需要保持同步。请注意级联值。fixed

@page "/"
@inject IServiceProvider ServiceProvider

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>
<CascadingValue Value=_myStateProvider IsFixed>
    <MyComponent />
    <TimeStampSetter />
    <TimeStampViewer />
    <TimeStampViewer />
    <TimeStampViewer />
    <TimeStampViewer />
    <TimeStampViewer />
    <TimeStampSetter />

</CascadingValue>

@code {
    private TimeStampProvider _myStateProvider = default!;

    protected override void OnInitialized()
    {
        // creates a new instance of TimeStampProvider in the context of the DI service container
        // which populates any DI services in the object
        _myStateProvider = ActivatorUtilities.CreateInstance<TimeStampProvider>(ServiceProvider);

        ArgumentNullException.ThrowIfNull(_myStateProvider);
    }
}

测试一下,你会发现一切都保持同步!

enter image description here