如何确保Blazor中OnInitializedAsync仅执行一次?当前判断方案失效
Blazor OnInitializedAsync 仅加载一次数据失效的解决方法
问题原因
你用tableLoading实例变量做判断无效,是因为每次组件重新初始化(比如路由跳转返回、父组件重渲染导致子组件重建)时,这个实例变量会被重置为默认值false,相当于判断逻辑根本没起到作用。
解决方案
1. 使用静态字段+线程锁(简单场景)
把加载状态改成静态变量,让所有组件实例共享这个状态,同时加锁避免并发问题:
private static bool _tableLoading; private static readonly object _lockObj = new object(); protected override async Task OnInitializedAsync() { lock (_lockObj) { if (_tableLoading) { return; } _tableLoading = true; } try { users = await userService.GetSome(1, userType); _total = await userService.GetCount(userType); } finally { lock (_lockObj) { _tableLoading = false; } } Console.WriteLine("OnInitializedAsync"); }
2. 服务层缓存数据(推荐)
把数据缓存逻辑放到单例的UserService里,组件直接拿缓存好的数据,不用管加载状态:
// UserService 示例(确保服务注册为单例) public class UserService { private List<User> _cachedUsers; private int _cachedTotal; private readonly object _lockObj = new object(); private readonly YourDbContext _dbContext; public UserService(YourDbContext dbContext) { _dbContext = dbContext; } public async Task<List<User>> GetSome(int page, int userType) { lock (_lockObj) { if (_cachedUsers != null) { return _cachedUsers; } } // 实际数据库查询逻辑 var users = await _dbContext.Users .Where(u => u.Type == userType) .ToListAsync(); lock (_lockObj) { _cachedUsers = users; } return users; } public async Task<int> GetCount(int userType) { lock (_lockObj) { if (_cachedTotal != 0) { return _cachedTotal; } } var count = await _dbContext.Users .CountAsync(u => u.Type == userType); lock (_lockObj) { _cachedTotal = count; } return count; } }
组件里直接调用即可,不用做加载状态判断:
protected override async Task OnInitializedAsync() { // 服务会自动返回缓存数据,无需重复查询 users = await userService.GetSome(1, userType); _total = await userService.GetCount(userType); Console.WriteLine("OnInitializedAsync"); }
3. 持久化组件状态(.NET 6+ 路由组件适用)
如果是路由组件,用PersistComponentState特性保存状态,避免组件重建时丢失数据:
[PersistComponentState] public partial class YourComponent { private bool tableLoading; private List<User> users; private int _total; [Inject] private IPersistentComponentState PersistentState { get; set; } private PersistingComponentStateSubscription _subscription; protected override void OnInitialized() { // 注册状态持久化回调 _subscription = PersistentState.RegisterOnPersisting(PersistCurrentState); // 恢复之前保存的状态 if (PersistentState.TryGetFromJson<List<User>>("cachedUsers", out var savedUsers)) { users = savedUsers; } if (PersistentState.TryGetFromJson<int>("cachedTotal", out var savedTotal)) { _total = savedTotal; } } private Task PersistCurrentState() { // 保存当前状态 PersistentState.PersistAsJson("cachedUsers", users); PersistentState.PersistAsJson("cachedTotal", _total); return Task.CompletedTask; } protected override async Task OnInitializedAsync() { // 已有缓存数据直接返回 if (users != null) return; if (tableLoading) return; tableLoading = true; users = await userService.GetSome(1, userType); _total = await userService.GetCount(userType); tableLoading = false; Console.WriteLine("OnInitializedAsync"); } public void Dispose() { _subscription.Dispose(); } }
内容的提问来源于stack exchange,提问作者lyj
相关产品推荐
相关产品推荐

