Blazor Syncfusion MultiSelect大数据场景优化实现方案咨询
Blazor WASM Syncfusion MultiSelect 大数据量性能优化方案
针对你在5000条员工数据下使用Syncfusion MultiSelect出现的卡顿、崩溃问题,结合按FullName或人员编号(FullInfo组合字段)搜索的需求,给出以下优化方案:
1. 完善虚拟滚动配置
你已开启EnableVirtualization,但缺少关键的项高度配置和自定义内容模板,导致虚拟滚动无法精准计算渲染范围,仍会加载大量DOM节点。补充配置如下:
<SfMultiSelect @ref="mulObj" TValue="List<string>" TItem="EmployeeQueryModel" Mode="VisualMode.Box" EnableRtl="true" Query="LocalDataQuery" EnableVirtualization="true" ItemHeight="40" <!-- 明确每个选项高度,虚拟滚动核心配置 --> Placeholder="Please choose your employees..." AllowFiltering="true" DataSource="employeesDropDown" @bind-Value="CommandModel.MultiSelectEmployees"> <MultiSelectFieldSettings Value="PersonnelCode" Text="FullInfo"></MultiSelectFieldSettings> <!-- 自定义虚拟滚动模板,降低DOM复杂度 --> <VirtualizationContentTemplate> @context.FullInfo </VirtualizationContentTemplate> <MultiSelectEvents TItem="EmployeeQueryModel" TValue="List<string>" Filtering="@FilteringHandler" Cleared="@ClearedHandler"> </MultiSelectEvents> </SfMultiSelect>
2. 防抖过滤+提前触发搜索
原方案输入4个字符才触发后端请求,用户体验差且无防抖逻辑易导致频繁请求。改为输入2个字符+300ms防抖,平衡搜索精度与请求频率:
private CancellationTokenSource? _filterCts; private async Task FilteringHandler(FilteringEventArgs args) { args.PreventDefaultAction = true; var filterText = args.Text.Trim(); // 防抖:取消未完成的请求 _filterCts?.Cancel(); _filterCts = new CancellationTokenSource(); if (filterText.Length < 2) { // 字符过少时返回空列表,避免加载全量数据 employeesDropDown.Clear(); await mulObj.RefreshDataAsync(); return; } try { // 延迟300ms执行,避免连续输入频繁请求 await Task.Delay(300, _filterCts.Token); // 后端分页查询:每次仅返回20条匹配数据,配合虚拟滚动按需加载 var filteredResult = await GetFilteredEmployeesPaged(filterText, pageSize: 20); // 合并已选员工,避免已选项被过滤 var selectedCodes = CommandModel.MultiSelectEmployees.ToHashSet(); var selectedItems = selectedEmployees.Where(e => selectedCodes.Contains(e.PersonnelCode)); employeesDropDown.Clear(); employeesDropDown.AddRange(filteredResult.Concat(selectedItems).DistinctBy(e => e.PersonnelCode)); // 仅调用FilterAsync即可,无需重复执行RefreshDataAsync await mulObj.FilterAsync(employeesDropDown, LocalDataQuery); } catch (OperationCanceledException) { // 忽略取消的请求 } }
3. 后端分页+精准过滤
修改后端GetFilteredEmployeesPaged接口,支持:
- 同时模糊匹配
PersonnelCode和FullName(直接匹配原字段比匹配组合字段FullInfo更高效) - 分页返回结果(每次20条),避免一次性返回大量数据
示例后端查询伪代码:
public async Task<List<EmployeeQueryModel>> GetFilteredEmployeesPaged(string filterText, int pageSize) { return await dbContext.Employees .Where(e => e.PersonnelCode.Contains(filterText) || e.FullName.Contains(filterText)) .OrderBy(e => e.FullName) .Take(pageSize) .ToListAsync(); }
4. 移除冗余的已选项维护
你同时通过@bind-Value和OnValueSelect/ValueRemoved维护已选员工,存在重复操作和内存冗余。直接通过绑定值获取已选项即可:
// 删除OnValueSelectHandler和ValueRemovedHandler // 已选员工从绑定值映射 private List<EmployeeQueryModel> SelectedEmployees => employeesDropDown.Where(e => CommandModel.MultiSelectEmployees.Contains(e.PersonnelCode)).ToList(); private void ClearedHandler(MouseEventArgs args) { CommandModel.MultiSelectEmployees = new List<string>(); // 无需手动重置selectedEmployees,绑定值会自动同步 }
5. 优化数据源更新方式
避免每次过滤都创建新List,改用Clear()+AddRange()减少内存分配:
// 替换原employeesDropDown赋值逻辑 employeesDropDown.Clear(); employeesDropDown.AddRange(filteredResult.Concat(selectedItems).DistinctBy(e => e.PersonnelCode));
内容的提问来源于stack exchange,提问作者Milad Abdi
相关产品推荐
相关产品推荐

