Blazor单例状态容器生成多实例 点击任意处关闭Avatar弹窗异常
问题根因排查(按出现概率从高到低排序)
1. 事件冒泡导致的逻辑假象(90%概率是这个问题)
你当前的代码中Avatar组件的点击切换事件没有阻止事件冒泡,点击Avatar的触发按钮时,点击事件会逐层向上冒泡,最终触发MainLayout里page元素绑定的CloseAvatar方法。
实际执行顺序为:
- 点击Avatar的触发按钮 → 执行
SetToggleAvatar→CollapseAvatar被设置为false - 事件冒泡到上层page元素 → 执行
SetCloseAvatar→CollapseAvatar立刻被改回默认值true
你误以为拿到了不同服务实例,实际上是同一个实例被两个方法先后修改,看起来就像Toggle操作没生效。
修复方式:在Avatar的切换点击事件上添加停止冒泡修饰符
<!-- 给你原来触发ToggleAvatarView的元素加上@onclick:stopPropagation --> <button @onclick="ToggleAvatarView" @onclick:stopPropagation> 切换头像弹窗 </button>
2. 服务注入错误,存在手动实例化服务的情况
如果两个位置中任意一个没有通过Blazor的DI容器获取服务,而是手动写了new StateContainerService(),就会拿到独立的新实例。
检查Avatar组件和MainLayout的服务注入代码,确认使用的是官方注入方式:
@inject StateContainerService StateContainerService <!-- 禁止手动new实例:private StateContainerService StateContainerService = new(); -->
3. 服务重复注册覆盖了Singleton配置
检查Program.cs中AddSingleton注册语句之后,有没有其他地方重复注册了StateContainerService,比如后续加了AddScoped或者AddTransient注册同一个服务,后面的注册会覆盖前面的Singleton配置,导致拿到不同实例。
4. Blazor WebAssembly页面跳转场景(仅WebAssembly项目可能)
如果你是Blazor WebAssembly项目,并且用了传统a标签跳转而非NavLink组件跳转,页面刷新后Singleton服务会重置为初始值,看起来就像拿到了新实例,统一使用NavLink跳转即可。
额外提醒:你当前把状态服务注册为Singleton,所有访问应用的用户会共享同一个弹窗状态,实际生产环境建议改成
AddScoped注册,保证每个用户的弹窗状态独立。
内容的提问来源于stack exchange,提问作者fuzzybear
相关产品推荐
相关产品推荐

