Blazor组件调用StateHasChanged/this.StateHasChanged无渲染效果问题排查
问题根源
你的导航菜单组件是独立的LayoutComponentBase子类实例,和CategoryAdministration页面属于两个完全隔离的组件对象。你在CategoryAdministration中调用的GetCategoriesNav仅会修改当前页面实例下的NavCategories、NavCategoryPages字段,完全不会同步到布局中的导航菜单组件,因此导航菜单不会触发重渲染。
解决方案(推荐:全局状态通知服务)
这种方式实现简单,适用于跨组件同步状态的场景,没有层级限制:
步骤1:创建状态通知服务
public class CategoryStateService { // 分类数据变更事件 public event Func<Task> OnCategoryChanged; public async Task NotifyChangedAsync() { if (OnCategoryChanged != null) { await OnCategoryChanged.Invoke(); } } }
步骤2:注册服务
在Program.cs中注册服务:
// Blazor WebAssembly 项目注册为单例 builder.Services.AddSingleton<CategoryStateService>(); // Blazor Server 项目注册为 Scoped,避免多用户互相干扰 // builder.Services.AddScoped<CategoryStateService>();
步骤3:导航菜单组件订阅通知
修改你的导航菜单代码:
@inject CategoryStateService CategoryState @inject CategoryService categoryService @inject CategoryPageService categoryPageService @implements IAsyncDisposable @* 渲染部分不变,建议优化循环逻辑见下文 *@ @code { private List<Category> NavCategories = new List<Category>(); private List<CategoryPage> NavCategoryPages = new List<CategoryPage>(); protected override async Task OnInitializedAsync() { await GetCategoriesNav(); // 订阅分类变更通知 CategoryState.OnCategoryChanged += GetCategoriesNav; } public async Task GetCategoriesNav() { NavCategories = await categoryService.GetCategories(); NavCategoryPages = await categoryPageService.GetCategoryPages(); // 拉取数据后主动触发重渲染 StateHasChanged(); } // 组件销毁时取消订阅,避免内存泄漏 public async ValueTask DisposeAsync() { CategoryState.OnCategoryChanged -= GetCategoriesNav; } }
步骤4:增改分类后触发通知
修改CategoryAdministration中的代码,增改成功后不用调用本地的GetCategoriesNav,直接发通知即可:
@inject CategoryStateService CategoryState // 新增分类逻辑 async Task AddCategory() { Category thisCategory = new(); var param = new DialogParameters { ["category"] = thisCategory }; IDialogReference dialog = DialogService.Show<CategoryDialog>("Add Category", param); DialogResult result = await dialog.Result; if(!result.Cancelled) { GetCategories(); // 触发全局通知,导航菜单会自动拉取最新数据刷新 await CategoryState.NotifyChangedAsync(); } } // 编辑分类逻辑同理 async Task EditCategory(Category category) { category = await categoryService.EditCategory(category); var param = new DialogParameters { ["category"] = category }; var dialog = DialogService.Show<CategoryDialog>("Edit Category", param); DialogResult result = await dialog.Result; if (!result.Cancelled) { GetCategories(); await CategoryState.NotifyChangedAsync(); } }
额外优化:修复导航菜单重复渲染问题
你当前的导航菜单循环逻辑存在冗余嵌套,会导致同一个分类重复渲染多次,优化后的渲染代码:
<MudNavMenu Style="color:white"> @foreach (Category category in NavCategories) { var currentCategoryPages = NavCategoryPages.Where(p => p.CategoryId == category.Id).ToList(); if(currentCategoryPages.Any()) { <MudNavGroup Title=@category.Name> @foreach(CategoryPage page in currentCategoryPages) { <MudNavLink>@page.PageName</MudNavLink> } </MudNavGroup> } else { <MudNavLink>@category.Name</MudNavLink> } } </MudNavMenu>
内容的提问来源于stack exchange,提问作者Rowin
相关产品推荐
相关产品推荐

