使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件
Posted
技术标签:
【中文标题】使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件【英文标题】:Refresh blazor server child component from parent component by using StateHasChanged 【发布时间】:2021-10-13 15:03:56 【问题描述】:Blazor 重新加载子组件
我的一个组件如下所示(在我的例子中这是一个子组件)
ListMetaData 组件/子组件
<table>
bind the list of items from model to the table
</table>
@code
List<MetaDataViewModel> model= new List<MetaDataViewModel>();
protected override async Task OnInitializedAsync()
await LoadMetaDataList();
public async Task LoadMetaDataList()
model= dbContextService.fetchFromDb();
public void Refresh()
StateHasChanged();
我有一个父组件,如下所示
@page "/settings/metadata"
@inject IDialogService DialogService
@inject ISnackbar Snackbar
<MudGrid>
<MudItem >
<MudButton OnClick="@((e) => AddNewmetaDataEvent())"
Class="ma-1">Add new</MudButton>
</MudItem>
<MudItem xs="12" >
<ListMetaData @ref="_listComponent" ></ListMetaData>
</MudItem>
</MudGrid>
@code
private ListMetaData _listComponent;
async Task AddNewmetaDataEvent()
var dialog = DialogService.Show<AddMetaDataDialog>("Add new MetaData");
var result = await dialog.Result;
if (!result.Cancelled)
Snackbar.Add("Please wait while the list is getting updated", Severity.Info);
_listComponent.Refresh();
else
Snackbar.Add("Dialog cancelled without performing any action", Severity.Normal);
按钮点击事件的父组件会出现一个对话框,允许用户向数据库添加新项目。
在关闭对话框时,我正在尝试重新加载子组件中的项目列表
但即使在使用 StateHasChanged() 之后,我的列表也没有更新。我必须重新加载页面才能看到子组件中修改后的项目列表
我关注了来自社区 How to refresh a blazor sub/child component within a main/parent component? 的几个答案,但没有得到我的代码中不正确的地方
【问题讨论】:
您已将 AddNewmetaDataEvent 方法包装在async void
结构中。只需使用OnClick="AddNewmetaDataEvent"
。
【参考方案1】:
这应该可以(但是请参阅注释)
@page "/settings/metadata"
@inject IDialogService DialogService
@inject ISnackbar Snackbar
<MudItem >
<MudButton OnClick="@((e) => AddNewmetaDataEvent())"
Class="ma-1">Add new</MudButton>
</MudItem>
@if (_updating)
<span>Updating</span>
else
<MudGrid>
<MudItem xs="12" >
<ListMetaData @ref="_listComponent" ></ListMetaData>
</MudItem>
</MudGrid>
@code
private ListMetaData _listComponent;
private bool _updating;
async Task AddNewmetaDataEvent()
_updating = true; // forces UI dom refresh
var dialog = DialogService.Show<AddMetaDataDialog>("Add new MetaData");
var result = await dialog.Result;
if (!result.Cancelled)
Snackbar.Add("Please wait while the list is getting updated", Severity.Info);
else
Snackbar.Add("Dialog cancelled without performing any action", Severity.Normal);
_updating = false; // forces UI dom refresh
尽量避免通过捕获引用来更新子组件。我知道像 SyncFusion 等 UI 库会强制使用这种 @ref / Refresh() 模式。尽可能避免它,而是将数据作为参数传递。这将使您免于这些类型的手动刷新。
【讨论】:
将数据作为参数传递给子组件?在我的情况下,子组件用于显示列表以及我们必须传递什么参数?决定是否重新加载的标志?同样在答案中,我们是否需要调用 Refresh()?我看不到任何地方都提到过 在 if ... else 语句中,渲染块之一。当 'updating' 标志为真时,MudGrid 组件将从 DOM 中移除。当它设置为 false 时,将从头开始渲染 MudGrid 组件。所以你不需要手动刷新任何东西。此外,在 ChildComponent 问题上,您应该将 List 发送到您的子组件。 (我正在稍微更新答案,因为它可能会导致运行时问题。) 我同意这个答案,await LoadMetaDataList();
不应该在 ListMetaData 组件中,而应该在父组件中。然后<ListMetaData data=listData />
解决了所有更新问题。以上是关于使用 StateHasChanged 从父组件刷新 Blazor 服务器子组件的主要内容,如果未能解决你的问题,请参考以下文章
Blazor 组件在 StateHasChanged() 之后未更新
Blazor 中的 StateHasChanged() 与 InvokeAsync(StateHasChanged)