You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:05:32