Blazor Server跨目录Razor组件如何实时获取更新共享变量值
问题原因
你用public static字段存值无法自动更新UI的核心逻辑很简单:Blazor组件的自动重渲染依赖自身的StateHasChanged()方法触发,你修改static字段时,LoginDisplay组件完全没有收到值变更的通知,自然不会主动刷新UI,只有整页手动重载时,组件才会重新读取static字段的最新值完成渲染。
额外注意:Blazor Server是服务端运行的,static字段是全局共享的,多个用户访问时会出现数据串流的问题,不要用static存用户侧的状态数据。
最简实现方案
用Blazor原生的轻量状态服务实现跨组件值同步,全程3步,不需要引入额外第三方库:
第一步:创建共享状态类
在项目中新建一个状态类,专门存需要跨组件共享的计数值,同时提供值变更的事件通知:
public class CounterState { private int _currentCount = 0; // 公开属性供所有组件读取计数值 public int CurrentCount => _currentCount; // 值变更事件,所有订阅的组件会收到更新通知 public event Action? OnCountChanged; // 累加计数的公共方法 public void AddCount() { _currentCount++; // 值修改后触发事件,通知所有订阅组件刷新 OnCountChanged?.Invoke(); } }
第二步:注册状态服务
打开项目的Program.cs,在应用构建前把状态类注册为Scoped生命周期,这个生命周期在Blazor Server中对应单个用户的连接电路,不会出现多用户数据串流的问题:
// 加在builder.Build() 代码行之前即可 builder.Services.AddScoped<CounterState>();
第三步:修改对应组件代码
- 修改
Pages目录下的Counter.razor,移除原来的私有currentCount字段,注入状态服务,按钮点击时调用服务的累加方法:
@page "/counter" @inject CounterState CounterState <PageTitle>Counter</PageTitle> <h1>Counter</h1> <p role="status">Current count: @CounterState.CurrentCount</p> <button class="btn btn-primary" @onclick="CounterState.AddCount">Click me</button>
- 修改
Shared目录下的LoginDisplay.razor,注入状态服务,订阅值变更事件,收到通知时主动触发自身UI刷新,记得组件销毁时取消事件订阅避免内存泄漏:
@inject CounterState CounterState @implements IDisposable <!-- 原有LoginDisplay的登录、用户信息等代码保留,仅新增计数值展示部分 --> <p>Counter Value: @CounterState.CurrentCount</p> @code { protected override void OnInitialized() { // 组件初始化时订阅计数变更事件 CounterState.OnCountChanged += RefreshUI; } private void RefreshUI() { // 跨线程触发UI更新需要用InvokeAsync包裹,避免线程异常 InvokeAsync(StateHasChanged); } public void Dispose() { // 组件销毁时取消事件订阅,防止内存泄漏 CounterState.OnCountChanged -= RefreshUI; } }
效果说明
改完之后只要在Counter页面点击按钮累加计数,LoginDisplay组件会立刻拿到最新值自动更新UI,不需要手动刷新页面,也不会出现多用户数据串流的问题。这个方案是Blazor跨层级组件传值的通用方案,不管组件嵌套多深、在哪个目录都能用。
内容的提问来源于stack exchange,提问作者Mdarende
相关产品推荐
相关产品推荐

