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

AngularJS中oi-select加载大数据耗时过长的优化需求

解决AngularJS滚动加载自定义oi-select指令时的搜索范围问题

你已经实现了滚动加载的雏形,但搜索仅覆盖当前渲染数据的核心问题,本质是把过滤逻辑放在了已渲染的ng-repeat子集上,而非先在完整数据源过滤再分页。下面是一套完整的优化方案,既能解决搜索范围问题,还能进一步提升初始加载性能:

1. 重构数据结构:分离完整数据源与渲染子集

在directive作用域中维护三个关键数组,避免数据混淆:

  • fullOptionList: 存储全部3000条原始数据,仅初始化一次
  • filteredOptionList: 存储经过搜索过滤后的完整结果数组
  • displayedOptionList: 存储当前需要渲染的分页子集(滚动加载时动态扩展)

同时添加两个控制变量:

  • currentLimit: 当前渲染的条目数量(初始设为50)
  • pageSize: 每次滚动加载新增的条目数量(比如50)

2. 优化初始数据处理:降低时间复杂度

你原来的双重angular.forEach匹配选中项,时间复杂度是O(n*m),数据量大时会非常慢。改成用Set快速匹配,把时间复杂度降到O(n+m):

// 初始化完整数据源
scope.fullOptionList = parentScope[scope.parentListName].sort();
scope.currentLimit = 50;
scope.pageSize = 50;

// 用Set存储选中项,快速匹配选中状态
var selectedItems = new Set(scope.optionListSelectedList);
scope.tempOptionList = scope.fullOptionList.map(item => ({
  val: item,
  check: selectedItems.has(item),
  originalcheck: selectedItems.has(item)
}));
// 初始状态下,过滤数据集等于完整数据集
scope.filteredOptionList = angular.copy(scope.tempOptionList);

3. 修改搜索逻辑:先过滤完整数据集,再分页渲染

当用户输入搜索关键词typeFilterOptions时,直接在完整数据集上执行过滤,更新filteredOptionList,然后重置currentLimit,确保从过滤结果的开头开始渲染:

scope.$watch('typeFilterOptions', function(newVal) {
  if (!newVal) {
    // 无搜索词时恢复为完整数据集
    scope.filteredOptionList = angular.copy(scope.tempOptionList);
  } else {
    const lowerFilter = newVal.toLowerCase();
    // 在完整数据集上执行过滤
    scope.filteredOptionList = scope.tempOptionList.filter(item => {
      const targetContent = (item.label || item.val).toString().toLowerCase();
      return targetContent.includes(lowerFilter);
    });
  }
  // 重置渲染数量,从过滤结果的第一条开始显示
  scope.currentLimit = scope.pageSize;
});

4. 调整滚动加载逻辑:基于过滤后的数据集扩展渲染

修改addmoreitems函数,让它在filteredOptionList的基础上增加currentLimit,直到覆盖全部过滤结果:

scope.addmoreitems = function() {
  const remainingItems = scope.filteredOptionList.length - scope.currentLimit;
  if (remainingItems > 0) {
    // 每次新增pageSize条,剩余不足时取剩余数量
    scope.currentLimit += Math.min(scope.pageSize, remainingItems);
  }
};

5. 更新模板:简化渲染逻辑,减少性能开销

把ng-repeat的数据源改成filteredOptionList | limitTo: currentLimit,同时移除模板中的ng-if过滤条件(已在filteredOptionList中处理),并用一次性绑定减少watchers:

<div ng-repeat="optionVal in filteredOptionList | limitTo: currentLimit | orderBy : ['-originalcheck','+label'] track by optionVal.val" prevent-close>
  <label class="checkbox">
    <input type="checkbox" name="checkbox1" ng-checked="optionVal.check" ng-model="optionVal.check" ng-change="checking()"/>
    <span class="checkbox__input"></span>
    <span class="checkbox__label" style="color:#A9A9A9;">{{::optionVal.label || optionVal.val}}</span>
  </label>
</div>

这里的track by避免重复渲染相同条目,{{::}}是一次性绑定,能大幅减少AngularJS的watchers数量,提升渲染流畅度。

额外性能优化建议

  • 滚动监听事件要在directive销毁时解绑(用$destroy事件),避免内存泄漏
  • 如果orderBy开销较大,可以在过滤后提前对filteredOptionList排序,而非在模板中使用过滤器
  • 若数据更新频率低,可考虑用$watchCollection替代$watch,减少不必要的digest循环

这样调整后,搜索会覆盖全部3000条数据,滚动加载也会基于搜索结果动态扩展,同时初始加载和渲染性能都会得到明显提升。

内容的提问来源于stack exchange,提问作者Sudarshan Kalebere

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:47:42