Blazor中在组件、路由、页面间共享对象的实现方案
解决方案:用单例服务实现全局共享数据
1. 定义数据模型类
先创建存储文件解析后数据的实体类,根据你的实际数据结构调整:
public class AppDatabase { // 对应文件中的数据库字段,自行扩展 public string DbName { get; set; } public List<DataRecord> Records { get; set; } = new(); } public class DataRecord { // 数据项的具体字段 public int Id { get; set; } public string Content { get; set; } }
2. 创建单例服务类
写一个服务类管理全局数据,负责文件解析和数据共享:
public class DatabaseService { // 全局唯一的数据库对象 public AppDatabase CurrentDb { get; private set; } // 加载并解析文件的方法 public async Task LoadAndParseFile(string filePath) { // 读取文件内容,这里以文本文件为例,根据你的文件类型调整解析逻辑 var fileContent = await File.ReadAllTextAsync(filePath); // 解析内容到CurrentDb,比如用JSON反序列化或自定义解析逻辑 CurrentDb = JsonSerializer.Deserialize<AppDatabase>(fileContent); // 触发更新事件,通知所有组件数据变化 OnDbUpdated?.Invoke(); } // 用于通知组件数据更新的事件 public event Action OnDbUpdated; }
3. 注册单例服务
在Program.cs里将服务注册为单例,确保整个应用生命周期只有一个实例:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); // 注册单例服务 builder.Services.AddSingleton<DatabaseService>(); var app = builder.Build(); // ... 其他中间件配置代码
4. 在MainLayout中处理文件选择
利用MainLayout的全局特性,在这里添加文件选择逻辑,调用服务加载数据:
@inject DatabaseService DbService @implements IDisposable <NavMenu /> <div class="main"> <div class="top-row px-4"> <!-- 文件选择控件 --> <input type="file" @onchange="HandleFileSelect" accept=".json,.txt" /> </div> <div class="content px-4"> @Body </div> </div> @code { protected override void OnInitialized() { // 订阅数据更新事件,可选 DbService.OnDbUpdated += UpdateLayoutUI; } private async Task HandleFileSelect(InputFileChangeEventArgs e) { if (e.File == null) return; // 临时保存文件(Blazor Server端示例,WebAssembly端读取方式略有不同) var tempPath = Path.GetTempFileName(); using var stream = new FileStream(tempPath, FileMode.Create); await e.File.OpenReadStream().CopyToAsync(stream); // 调用服务解析文件 await DbService.LoadAndParseFile(tempPath); } private void UpdateLayoutUI() { // 刷新布局UI(如果需要) StateHasChanged(); } public void Dispose() { // 取消事件订阅,避免内存泄漏 DbService.OnDbUpdated -= UpdateLayoutUI; } }
5. 在任意组件中访问和更新数据
直接注入DatabaseService就能获取全局数据,还能响应数据变化:
@inject DatabaseService DbService @implements IDisposable <h3>数据库内容展示</h3> @if (DbService.CurrentDb != null) { <p>数据库名称:@DbService.CurrentDb.DbName</p> <ul> @foreach (var record in DbService.CurrentDb.Records) { <li>ID: @record.Id | 内容: @record.Content</li> } </ul> <button @onclick="UpdateDbData">修改数据库名称</button> } else { <p>请先选择数据库文件</p> } @code { protected override void OnInitialized() { // 订阅数据更新事件,自动刷新UI DbService.OnDbUpdated += RefreshComponent; } private void RefreshComponent() { StateHasChanged(); } private void UpdateDbData() { if (DbService.CurrentDb == null) return; // 直接修改全局数据 DbService.CurrentDb.DbName = "更新后的数据库名称"; // 触发事件通知所有组件更新 DbService.OnDbUpdated?.Invoke(); } public void Dispose() { DbService.OnDbUpdated -= RefreshComponent; } }
关键说明
- 不需要通过路由或组件参数传递数据,所有组件通过依赖注入直接获取同一个服务实例,共享
CurrentDb对象。 - 单例服务在应用启动时创建,文件只会被解析一次(除非主动调用
LoadAndParseFile重新加载)。 - 通过服务内的
OnDbUpdated事件,能实现跨组件的数据更新通知,确保所有组件UI同步变化。
内容的提问来源于stack exchange,提问作者DaveK
相关产品推荐
相关产品推荐

