Blazor Server循环中如何避免异步方法的事件委托重复创建
异步场景下Blazor循环渲染事件委托重复创建的解决方案
核心结论:Blazor的@onclick事件处理器原生支持Func<Task>类型的异步委托,不需要额外嵌套lambda表达式,直接绑定预创建的委托即可避免重复生成。
具体实现步骤
- 第一步:修改自定义Button类的委托属性类型,将
Action替换为Func<Task> - 第二步:在初始化阶段预创建所有异步委托,存储到Button实例中
- 第三步:Razor模板中直接绑定
@onclick="button.Action",不需要额外包装异步lambda
完整代码示例
Razor渲染部分
@foreach (var button in _buttons) { <div class="col-3 mb-2"> <button @key="button.Id" @onclick="button.Action" class="btn btn-sm"> @button.Index </button> </div> }
逻辑代码部分
@code { List<Button> _buttons = new(); List<NavItem> _navItems; protected override async Task OnInitializedAsync() { _navItems = await GetItemsFromDb(); for(int i = 0; i < _navItems.Count; i++) { var localI = i; var item = _navItems[i]; _buttons.Add(new Button { Id = item.Id, Index = i + 1, // 预创建异步委托,仅初始化时生成一次 Action = async () => await SetCurrentAsync(localI) }); } } class Button { public int Id { get; set; } public int Index { get; set; } // 用Func<Task>替换Action存储异步委托 public Func<Task> Action { get; set; } } // 你的异步业务方法 private async Task SetCurrentAsync(int index) { // 业务逻辑实现 await Task.CompletedTask; } private async Task<List<NavItem>> GetItemsFromDb() { // 模拟数据查询 await Task.CompletedTask; return new List<NavItem>(); } class NavItem { public int Id { get; set; } } }
补充说明
- 该方案和同步场景的优化逻辑完全一致,所有委托仅在组件初始化阶段生成一次,后续重渲染不会重复创建新的委托实例
- 只有当渲染的元素/组件数量较大(通常超过100个)时该优化的收益才会明显,少量元素无需刻意做该优化
- 不要额外写
@onclick="async () => await button.Action()"这类嵌套lambda,会直接抵消优化效果
内容的提问来源于stack exchange,提问作者Amal K
相关产品推荐
相关产品推荐

