我有一个包含不同组件的 blazor 页面。
组件结构如下:
页 组件1 组件11 组件2
当组件 11 上发生事件时,组件 2 应该更新它的状态。
在同一个组件上我使用
OnStateChange
事件。
对于父组件的更新状态,我也可以使用 EventCallback。
但是在这里我需要将事件向上传递两个级别然后向下传递给其他组件。
看起来有点复杂。也许存在一些简单的方法来做到这一点。
事件冒泡可以自动实现吗?也许一些应用程序设置?
您需要使用某种形式的通知模式。
这是一个简单的提供者。请注意,它需要来自 DI 的
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
.的组件
时间戳设置器
<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);
}
}
测试一下,您会发现一切都保持同步!