当前位置: 首页 > news >正文

Blazor 删除数据后没有刷新页面

blazor 中,在servers页面,为何加上@rendermode InteractiveServer后,点击delete按钮后,列表没有立马消失,切换到其他页面后再返回改页面被删除条码就消失了。为什么呢?其中的NavigationManager.NavigateTo("/servers");不是重新导航到该页面吗?和点击其他页面再返回该页面有什么区别呢

你遇到的问题涉及到Blazor InteractiveServer模式下的状态保持导航行为。让我详细解释原因:

问题分析

1. InteractiveServer模式的状态保持

当你使用 @rendermode InteractiveServer 时,组件的状态在服务器端被保持。这意味着:

  • 组件实例在服务器内存中持续存在
  • 变量状态(如 servers 列表)不会在每次导航时自动重置
  • 这与之前的静态渲染模式行为完全不同

2. NavigationManager.NavigateTo("/servers") 的行为

// 这行代码并不会创建新的组件实例
NavigationManager.NavigateTo("/servers");

在InteractiveServer模式下:

  • 导航到同一路由不会重新创建组件实例
  • Blazor会尝试重用现有的组件实例
  • 因此 OnInitialized 等方法不会被再次调用
  • 字段初始化代码也不会重新执行

3. 为什么切换到其他页面再返回会更新

当前页面(/servers) → 其他页面(如 /home) → 返回 /servers

这个过程中:

  1. 离开 /servers 时,组件实例仍然在服务器内存中
  2. 导航到其他页面时,/servers 组件不再渲染但状态被保持
  3. 返回 /servers 时,组件被重新连接(reconnected)
  4. 重新连接会触发部分生命周期事件,可能包括重新绑定数据

解决方案

方案1:在删除后强制刷新数据(推荐)

修改 Delete 方法:

private void Delete(Server server)
{if (server.ServerId > 0){ServersRepository.DeleteServer(server.ServerId);// 重新获取数据并更新状态if (string.IsNullOrEmpty(selectedCity)){servers = ServersRepository.SearchServers(serverFilter);}else{servers = ServersRepository.GetServersByCity(selectedCity);}// 强制刷新UIStateHasChanged();}
}

方案2:使用导航管理器强制重新加载

private void Delete(Server server)
{if (server.ServerId > 0){ServersRepository.DeleteServer(server.ServerId);// 使用 forceLoad: true 强制完全重新加载页面NavigationManager.NavigateTo("/servers", forceLoad: true);}
}

方案3:使用 OnParametersSet 或 OnAfterRender 更新数据

protected override void OnParametersSet()
{// 每次参数变化时重新加载数据servers = ServersRepository.GetServersByCity(selectedCity);base.OnParametersSet();
}// 或者在导航时更新
protected override async Task OnAfterRenderAsync(bool firstRender)
{if (!firstRender){// 检查是否需要刷新数据}
}

方案4:使用状态管理(最佳实践)

创建状态服务:

// ServerStateService.cs
public class ServerStateService
{public event Action? OnChange;private List<Server> _servers = new();public List<Server> Servers => _servers;public void RefreshServers(string city){_servers = ServersRepository.GetServersByCity(city);NotifyStateChanged();}public void RemoveServer(int serverId){ServersRepository.DeleteServer(serverId);NotifyStateChanged();}private void NotifyStateChanged() => OnChange?.Invoke();
}// 在组件中注入
@inject ServerStateService ServerState// 在删除时调用
private void Delete(Server server)
{ServerState.RemoveServer(server.ServerId);
}// 订阅变化
protected override void OnInitialized()
{ServerState.OnChange += StateHasChanged;
}

方案5:使用 NavigationManager 的 LocationChanged 事件

@implements IDisposableprotected override void OnInitialized()
{NavigationManager.LocationChanged += HandleLocationChanged;LoadServers();
}private void HandleLocationChanged(object? sender, LocationChangedEventArgs e)
{if (e.Location.Contains("/servers")){LoadServers();StateHasChanged();}
}private void LoadServers()
{if (string.IsNullOrEmpty(selectedCity)){servers = ServersRepository.SearchServers(serverFilter);}else{servers = ServersRepository.GetServersByCity(selectedCity);}
}public void Dispose()
{NavigationManager.LocationChanged -= HandleLocationChanged;
}

关键区别总结

操作 效果 原因
NavigationManager.NavigateTo("/servers") 不刷新UI 重用现有组件实例
切换到其他页面再返回 UI刷新 组件重新连接,触发更新
forceLoad: true 完全刷新 绕过Blazor路由,使用传统导航

推荐使用方案1或方案4,这样可以在保持InteractiveServer模式优点的同时,确保UI状态正确更新。

在方案1中,如果不更新servers,直接使用StateHasChanged();,会有效果吗

不会有效果,因为 StateHasChanged() 只是通知Blazor"组件状态可能已改变,请重新渲染",但不会自动重新获取数据

详细解释:

1. StateHasChanged() 的工作原理

private void Delete(Server server)
{ServersRepository.DeleteServer(server.ServerId); // 从仓库删除StateHasChanged(); // 只是通知重新渲染// UI仍然显示旧的 servers 列表// 因为 servers 变量没有更新!
}
  • StateHasChanged() 只会触发UI重新渲染
  • 不会重新执行构造函数或初始化代码
  • 不会自动重新获取数据
  • 渲染时使用的仍然是旧的 servers 列表

2. 为什么需要更新 servers 变量

// 当前状态
servers = [Server1, Server2, Server3]  // 存储在组件实例中// 执行删除
ServersRepository.DeleteServer(server.ServerId)  // 仓库中的数据被删除
// 但组件的 servers 变量仍然是 [Server1, Server2, Server3]// 调用 StateHasChanged() 后
// Blazor 重新渲染,但使用的仍然是旧的 servers 列表
// 所以被删除的服务器仍然显示!

3. 验证测试

在你的代码中添加一些调试输出:

private void Delete(Server server)
{if (server.ServerId > 0){Console.WriteLine($"删除前 - 组件内 servers 数量: {servers.Count}");Console.WriteLine($"删除前 - 仓库中 servers 数量: {ServersRepository.GetServres().Count}");ServersRepository.DeleteServer(server.ServerId);Console.WriteLine($"删除后 - 组件内 servers 数量: {servers.Count}");Console.WriteLine($"删除后 - 仓库中 servers 数量: {ServersRepository.GetServres().Count}");StateHasChanged();  // 仅仅这个不会更新UI// 验证:重新获取数据并更新var updatedServers = ServersRepository.GetServersByCity(selectedCity);Console.WriteLine($"重新获取后 - servers 数量: {updatedServers.Count}");}
}

4. 解决方案对比

无效的方法

private void Delete(Server server)
{ServersRepository.DeleteServer(server.ServerId);StateHasChanged();  // 无效!UI不会更新
}

有效的方法1:重新获取数据

private void Delete(Server server)
{ServersRepository.DeleteServer(server.ServerId);// 重新获取数据servers = ServersRepository.GetServersByCity(selectedCity);StateHasChanged();  // 现在有效了!
}

有效的方法2:直接修改本地列表

private void Delete(Server server)
{ServersRepository.DeleteServer(server.ServerId);// 从本地列表中移除(避免重新查询)servers.Remove(server);StateHasChanged();  // 现在有效!
}

5. 最佳实践:状态更新 + UI通知

private void Delete(Server server)
{if (server.ServerId > 0){// 1. 更新数据源ServersRepository.DeleteServer(server.ServerId);// 2. 更新组件状态// 方法A:重新获取(确保数据一致)servers = string.IsNullOrEmpty(selectedCity) ? ServersRepository.SearchServers(serverFilter): ServersRepository.GetServersByCity(selectedCity);// 或方法B:直接移除(性能更好)// var itemToRemove = servers.FirstOrDefault(s => s.ServerId == server.ServerId);// if (itemToRemove != null) servers.Remove(itemToRemove);// 3. 通知UI更新StateHasChanged();// 可选:添加成功提示// await jsRuntime.InvokeVoidAsync("alert", "删除成功!");}
}

6. 为什么导航到其他页面再返回有效?

当切换到其他页面再返回时:

  1. 组件被重新连接(reconnected)
  2. 可能重新执行了部分初始化逻辑
  3. 从数据仓库重新获取了数据(因为 servers 可能被重新赋值)

但实际上,这在InteractiveServer模式下并不可靠,因为:

  • 如果组件实例被保持,可能不会重新初始化
  • 依赖特定的Blazor生命周期行为

总结:

StateHasChanged() 只是通知UI重新渲染,不包含数据更新逻辑。你必须确保组件使用的数据(如 servers 变量)与数据源(如 ServersRepository)保持同步。这就是为什么你需要手动更新 servers 变量的原因。

http://www.jsqmd.com/news/361690/

相关文章:

  • 收藏备用|从简历筛选案例入门,读懂AI系统架构4大发展阶段(小白/程序员必看)
  • 证券TA系统国产化选型盘点清单:主流文档数据库替换方案深度对比
  • AbMole小讲堂丨4-Hydroxytamoxifen:从雌激素受体拮抗到条件性基因调控的双功能分子
  • 这次终于选对了!8个降AI率平台测评:专科生必看的降AI率工具推荐
  • 分析2026年好用的GEO优化公司,河南地区口碑排名 - 工业品网
  • 【开题答辩全过程】以 海南农产品销售系统为例,包含答辩的问题和答案
  • 2026年飞贺纺织春亚纺面料选购指南,现货花色丰富且供应无风险 - myqiye
  • MedMO Grounding and Understanding Multimodal Large Language Model for Medical Images
  • Seeing Beyond Redundancy Task Complexity‘s Role in Vision Token Specialization in VLLMs
  • 聊聊佛山GEO推广优化方案,深圳光合道值得推荐 - 工业品网
  • 【大模型部署】零成本体验私有化部署llama3.1
  • 2026年河北永磁磁选机大型厂家年度排名,哪家性价比高? - mypinpai
  • Analyzing Diffusion and Autoregressive Vision Language Models in Multimodal Embedding Space
  • 2026年无锡口碑好的工作服老牌厂家推荐,专业工装工作服制作企业全解析 - 工业推荐榜
  • 剖析深圳有名的婚纱摄影专业公司,了解优势再做决定 - 工业推荐榜
  • 超大模型部署无压力!一键运行 Llama 3.1 405B 和 Mistral Large 2
  • 探寻全国做抖音培训的人物,铭泽国际实战经验丰富 - myqiye
  • ico多个尺寸用PNG,BMP哪个更小
  • 分析南通团体服源头厂家选择,哪家口碑比较靠谱 - 工业设备
  • 真心不骗你 10个AI论文平台深度测评,专科生毕业论文写作必备工具推荐!
  • 2026年常州工作服制造厂选哪家好,十大靠谱厂家排行榜揭晓 - 工业品牌热点
  • SPARC Separating Perception And Reasoning Circuits for Test-time Scaling of VLMs
  • 单采PBMC白细胞专业供应商+单采中外籍PBMC白细胞优质供应商,中外籍供体合规优选 - 品牌推荐大师1
  • RAG可以不用向量库?来围观一下这是怎么回事呢
  • 智能电子孵化箱温控计设计
  • 编写空调省电助手,根据室内温度,室外温度,人数,推荐空调最佳温度和模式,(制冷/制热,除湿),实时监控空调耗电量,生成省电报告,节省电费。
  • Relevance-aware Multi-context Contrastive Decoding for Retrieval-augmented Visual Question Answering
  • 2026年2月混凝土抗裂添加剂工厂推荐,工程抗裂配方与应用指南 - 品牌鉴赏师
  • 2026 昆明英语雅思培训教育机构推荐、雅思培训课程中心权威口碑榜单 - 老周说教育
  • 培训直播平台哪个好?2026实测不踩坑