Blazor应用中如何让组件变量与LocalStorage变量同步?
解决方案
方案1:全局主题事件服务(发布订阅模式)
创建一个全局可注入的主题服务,在主题切换时发布事件,所有需要响应的子组件订阅事件并执行更新逻辑。
- 定义主题服务:
public class ThemeService { // 主题切换事件 public event Action? ThemeChanged; // 触发事件的方法 public void NotifyThemeChanged() { ThemeChanged?.Invoke(); } }
- 在Program.cs中注册为单例服务:
builder.Services.AddSingleton<ThemeService>();
- 在MainLayout中注入服务,切换主题时触发事件:
@inject ThemeService ThemeService @inject ILocalStorageService LocalStorage <button @onclick="ToggleTheme">切换主题</button> @code { private async Task ToggleTheme() { // 更新LocalStorage中的主题样式值 var currentDiagramColor = await LocalStorage.GetItemAsync<string>("DiagramColor"); var newDiagramColor = currentDiagramColor == "#FFFFFF" ? "#000000" : "#FFFFFF"; var newLabelColor = newDiagramColor == "#FFFFFF" ? "#000000" : "#FFFFFF"; await LocalStorage.SetItemAsync("DiagramColor", newDiagramColor); await LocalStorage.SetItemAsync("LabelColor", newLabelColor); // 触发主题变更通知 ThemeService.NotifyThemeChanged(); } }
- 在包含SfChart的子组件中订阅事件,调用load()方法:
@inject ThemeService ThemeService @implements IDisposable <SfChart @ref="chartRef"> <!-- 图表配置 --> </SfChart> @code { private SfChart? chartRef; @inject ILocalStorageService LocalStorage protected override void OnInitialized() { ThemeService.ThemeChanged += OnThemeUpdated; } private async void OnThemeUpdated() { // 读取最新样式值并更新组件 DiagramColor = await LocalStorage.GetItemAsync<string>("DiagramColor"); LabelColor = await LocalStorage.GetItemAsync<string>("LabelColor"); // 刷新图表 await chartRef?.Load(); StateHasChanged(); } public void Dispose() { // 取消订阅避免内存泄漏 ThemeService.ThemeChanged -= OnThemeUpdated; } }
方案2:监听LocalStorage变化
利用LocalStorage的变更事件,直接监听主题相关键的变化,自动触发子组件更新。
- 在子组件中监听LocalStorage:
@inject ILocalStorageService LocalStorage @implements IDisposable <SfChart @ref="chartRef"> <!-- 图表配置 --> </SfChart> @code { private SfChart? chartRef; private IDisposable? storageSubscription; protected override async Task OnInitializedAsync() { // 初始化加载样式值 await LoadThemeValues(); // 监听指定键的变化 storageSubscription = LocalStorage.OnChanged.Subscribe(args => { if (args.Key is "DiagramColor" or "LabelColor") { InvokeAsync(async () => { await LoadThemeValues(); await chartRef?.Load(); StateHasChanged(); }); } }); } private async Task LoadThemeValues() { DiagramColor = await LocalStorage.GetItemAsync<string>("DiagramColor"); LabelColor = await LocalStorage.GetItemAsync<string>("LabelColor"); } public void Dispose() { storageSubscription?.Dispose(); } }
方案3:使用级联参数传递主题状态
通过级联参数将主题状态从MainLayout传递给所有子组件,子组件监听参数变化并执行更新。
- 在MainLayout中定义级联参数:
<CascadingValue Value="currentTheme" Name="CurrentTheme"> @Body </CascadingValue> <button @onclick="ToggleTheme">切换主题</button> @code { private ThemeModel currentTheme = new(); @inject ILocalStorageService LocalStorage private class ThemeModel { public string DiagramColor { get; set; } = "#FFFFFF"; public string LabelColor { get; set; } = "#000000"; } private async Task ToggleTheme() { // 更新主题状态 currentTheme.DiagramColor = currentTheme.DiagramColor == "#FFFFFF" ? "#000000" : "#FFFFFF"; currentTheme.LabelColor = currentTheme.LabelColor == "#000000" ? "#FFFFFF" : "#000000"; // 同步到LocalStorage await LocalStorage.SetItemAsync("DiagramColor", currentTheme.DiagramColor); await LocalStorage.SetItemAsync("LabelColor", currentTheme.LabelColor); StateHasChanged(); } }
- 在子组件中接收级联参数并响应变化:
<SfChart @ref="chartRef"> <!-- 图表配置 --> </SfChart> @code { private SfChart? chartRef; [CascadingParameter(Name = "CurrentTheme")] private ThemeModel? Theme { get; set; } protected override async Task OnParametersSetAsync() { if (Theme != null) { // 更新组件样式变量 DiagramColor = Theme.DiagramColor; LabelColor = Theme.LabelColor; // 刷新图表 await chartRef?.Load(); } } private class ThemeModel { public string DiagramColor { get; set; } = "#FFFFFF"; public string LabelColor { get; set; } = "#000000"; } }
以上方案均无需给@body加载的子组件添加@ref,通过事件驱动、存储监听或级联参数的方式,实现主题变更的全局通知与组件响应。
内容的提问来源于stack exchange,提问作者Aymen Abdessmad
相关产品推荐
相关产品推荐

