Blazor API调用完成后如何从子组件触发主RAZOR页面刷新并控制加载状态
解决方案
步骤1:改造Scoped服务AppState,增加状态管理和通知能力
你需要在AppState中加入加载状态标志、结果存储属性,以及状态变化通知事件,让所有订阅该事件的组件可以自动感知状态更新:
public class AppState { // 控制加载动画显示的布尔触发器 public bool IsLoading { get; private set; } // 存储API返回的搜索结果,替换为你实际的数据集类型 public List<SearchResultItem> SearchResults { get; private set; } = new(); // 状态变化通知事件 public event Action OnStateChanged; // 发起API请求前调用,开启加载状态 public void StartLoading() { IsLoading = true; NotifyStateChanged(); } // API返回数据后调用,更新结果并关闭加载状态 public void UpdateSearchResults(List<SearchResultItem> results) { IsLoading = false; SearchResults = results ?? new(); NotifyStateChanged(); } private void NotifyStateChanged() => OnStateChanged?.Invoke(); }
步骤2:改造SearchResults.razor页面
首先补充注入和接口实现
@page "/searchresults" @layout PageTopComponents @inject AppState AppState @inject NavigationManager NavigationManager @inject 你的API服务类 SearchApiService @implements IAsyncDisposable
修改渲染逻辑,直接通过AppState的状态判断展示内容
<MainContentComponent.razor> @if (AppState.IsLoading) { <!-- 你的加载动画代码 --> } else if (AppState.SearchResults.Any()) { @foreach (var item in AppState.SearchResults) { <!-- 渲染单条搜索结果 --> } } else { <p>暂无匹配结果</p> } <ContinueSearch.razor></ContinueSearch.razor> <Paginator.razor @ref="PaginatorComponentReference"> <ChildContent> <!-- 原有数据渲染逻辑 --> </ChildContent> </Paginator.razor> </MainContentComponent.razor>
补充@code块的逻辑,监听地址变化和状态更新
@code { public Paginator PaginatorComponentReference; protected override async Task OnInitializedAsync() { // 订阅地址变化事件:相同路由跳转时Blazor默认复用组件,不会触发初始化生命周期,需要手动监听地址变化 NavigationManager.LocationChanged += OnLocationChanged; // 订阅AppState的状态变化,状态更新时自动刷新页面 AppState.OnStateChanged += StateHasChanged; // 首次加载时执行搜索 await ExecuteSearchAsync(); } private async void OnLocationChanged(object sender, LocationChangedEventArgs e) { // 地址变化(包括查询参数变化)时重新执行搜索 await ExecuteSearchAsync(); } private async Task ExecuteSearchAsync() { // 解析当前查询参数 Uri uri = navigationManager.ToAbsoluteUri(System.Net.WebUtility.UrlDecode(navigationManager.Uri)); Dictionary<string, StringValues> queryStrings = QueryHelpers.ParseQuery(uri.Query); // 从queryStrings中提取搜索词、过滤条件等参数,拼装成你的API请求参数 var requestParams = new 你的API请求参数类(); // 示例:requestParams.Keyword = queryStrings["keyword"]; // 示例:requestParams.Filter1 = queryStrings["filter1"]; // 触发加载状态,调用API获取数据 AppState.StartLoading(); var searchResult = await SearchApiService.你的搜索方法(requestParams); AppState.UpdateSearchResults(searchResult); } // 页面销毁时取消订阅,避免内存泄漏 public async ValueTask DisposeAsync() { NavigationManager.LocationChanged -= OnLocationChanged; AppState.OnStateChanged -= StateHasChanged; } }
步骤3:过滤器组件逻辑无需修改
你原有NavigationManager.NavigateTo(href)的逻辑可以完全保留,现在页面已经可以感知到地址变化,自动触发重新搜索和页面刷新。
说明
之前生命周期方法不生效的核心原因:Blazor对于相同路由的跳转,默认会复用已有的组件实例,不会重新触发OnInitialized等初始化生命周期方法,因此你写的刷新逻辑只有首次进入页面时会执行。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

