.net-core - 使用事件时 Blazor 状态未在子组件之间更新
问题描述
我在 Blazor wasm 应用程序中有两个独立的组件,我试图在它们之间进行通信。在某些情况下,通信失败,我不明白为什么。
(简化的)设置如下
<ParentComponent>
<HeaderComponent>
<ProgressBar IsLoading="<Set by IsLoading property from header>" />
</HeaderComponent>
<ResultContainer />
</ParentComponent>
后面的代码如下所示:
public class ResultContainerStateManager
{
public event Action OnLoadStart;
public event Action OnLoadFinish;
public NotifyLoadStart() => this.OnLoadStart?.Invoke();
public NotifyLoadFinish() => this.OnLoadFinish?.Invoke();
}
public partial class HeaderComponent
{
[Inject]
public ResultContainerStateManager ResultContainerStateManager { get; set; }
private bool IsLoading { get; set; }
protected override void OnInitialized()
{
this.ResultContainerStateManager.OnLoadStart += () => this.IsLoading = true;
this.ResultContainerStateManager.OnLoadFinish += () => this.IsLoading = false;
base.OnInitializer();
}
}
public partial class ResultContainer
{
[Inject]
public ResultContainerStateManager ResultContainerStateManager { get; set; }
private bool IsLoading { get; set; }
protected override async Task OnParametersSetAsync()
{
<code>
if (shouldLoadData)
{
this.ResultContainerStateManager.NotifyLoadStart();
<more code>
this.ResultContainerStateManager.NotifyLoadFinish();
}
await base.OnParametersSetAsync();
}
}
public partial class ProgressBar
{
[Parameter]
public bool IsLoading { get; set; }
}
进度条中的IsLoading
参数是从IsLoading
属性中设置的HeaderComponent
,例如
<div id="headerComponent">
<More html here>
<ProgressBar IsLoading="@this.IsLoading" />
</div>
我认为这并不重要,但进度条本身使用该MatProgress
组件,如下所示:
@if (this.IsLoading)
{
<MatProgress Indeterminate="true" />
}
else
{
<Other html code>
}
问题是进度条在ResultContainer
执行NotifyLoadStart()
方法时开始,但在执行方法时并没有停止NotifyLoadFinish()
。我可以在调试时看到调用后的IsLoading
属性HeaderComponent
设置回false NotifyLoadFinish()
,但它对UI没有影响。
到目前为止我已经尝试过:
- 直接注入
ResultContainerStateManager
进度条 - 我尝试将事件更改为 Func 并完全异步处理
- 我尝试
await Task.Yield()
在每次Notify
通话后添加 - 我尝试
this.StateHasChanged()
在事件处理程序中和每次调用之后添加Notify
调用(我知道后者根本不应该改变任何东西,因为它不在同一个层次结构中)
这些都没有改变任何东西,我真的很想知道为什么。
我唯一的成功是使用EventCallbacks
而不是事件。但我在许多其他地方使用事件,它们似乎都工作正常。
有人可以告诉我为什么事件似乎失败了,以及如何解决这个问题?
解决方案
试试这个代码
public async Task OnLoadStart()
{
this.IsLoading = true;
await InvokeAsync(() => { StateHasChanged(); });
}
public async Task OnLoadFinish()
{
this.IsLoading = false;
await InvokeAsync(() => { StateHasChanged(); });
}
protected override void OnInitialized()
{
this.ResultContainerStateManager.OnLoadStart += OnLoadStart;
this.ResultContainerStateManager.OnLoadFinish += OnLoadFinish;
}
改变 :public event Action OnLoadStart;
到: public event Func<Task> OnLoadStart;
和: public event Action OnLoadFinish;
TP: public event Func<Task> OnLoadFinish;
在 HeaderComponent 组件中实现 IDisposable:
@implements IDisposable
public void Dispose()
{
this.ResultContainerStateManager.OnLoadStart -= OnLoadStart;
this.ResultContainerStateManager.OnLoadFinish -= OnLoadFinish;
}
尽可能开始异步编码。
推荐阅读
- javascript - 渲染中的 VueJS 错误:“TypeError:_vm.img.loadImg 不是函数
- arrays - 只想显示分配的 wordpress 类别
- selenium - 无法使用 Selenium IDE 选择选项
- chicken-scheme - 将鸡方案库嵌入C项目时无法加载任何鸡蛋
- python-3.x - 将循环的 numpy 直方图输出导出到没有数组信息和格式的列表
- animation - 动画组件以及框架中的自定义组件
- excel - Excel VBA - =在宏中查找
- c# - SQL SERVER - 动态 SQL 插入语句
- ios - WKWebView - 按钮在全屏模式下不可见
- sql - SQL 提取特殊字符 oracle 11g