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

如何先过滤数据再使用AngularJS的ng-repeat进行渲染?

解决AngularJS大数据量过滤后存到Scope并渲染的问题

Hey there! Let's tackle this problem step by step since you're dealing with a large dataset (50k+ records) and performance is definitely a concern here. Your current approach using a custom filter directly in ng-repeat has two main issues: it runs on every digest cycle (which is slow for huge datasets) and it doesn't persist the filtered results in your scope. Here's how to fix both:

核心解决方案:手动监听过滤条件,将结果存入Scope

Instead of relying on a filter in ng-repeat, we'll listen for changes to your search input, run the filtering logic manually, and store the filtered results in a dedicated scope variable. This way, ng-repeat only renders the already-filtered data, and we avoid redundant computations.

修改后的Controller代码

var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope, $http, $timeout) {
  // 存储原始完整数据
  $scope.materiale = [];
  // 存储过滤后的结果,供ng-repeat使用
  $scope.filteredMateriale = [];

  // 获取后端数据
  $http.get("http:source.php")
    .then(function(response) {
      $scope.materiale = response.data.records;
      // 初始化时默认显示全部数据(可根据需求调整为空)
      $scope.filterMaterials();
    });

  // 自定义过滤函数,和你之前的filter逻辑一致
  $scope.filterMaterials = function() {
    // 如果没有过滤条件,直接返回全部数据
    if (!$scope.filtru || $scope.filtru.trim() === '') {
      $scope.filteredMateriale = angular.copy($scope.materiale);
      return;
    }

    var filtered = [];
    var filtruMatch = new RegExp($scope.filtru, 'i');
    
    // 遍历原始数据执行过滤
    for (var i = 0; i < $scope.materiale.length; i++) {
      var item = $scope.materiale[i];
      // 匹配MATKL、MAKTX或MATNR字段
      if (filtruMatch.test(item.MATKL) || filtruMatch.test(item.MAKTX) || filtruMatch.test(item.MATNR)) {
        filtered.push(item);
      }
    }

    // 将过滤结果存入scope
    $scope.filteredMateriale = filtered;
  };

  // 监听过滤输入的变化,添加防抖优化(避免每次输入字符都立刻触发过滤)
  var debounceTimer;
  $scope.$watch('filtru', function(newVal, oldVal) {
    if (newVal !== oldVal) {
      // 清除之前的定时器,避免重复执行
      if (debounceTimer) {
        $timeout.cancel(debounceTimer);
      }
      // 延迟300ms执行过滤,用户停止输入后再计算
      debounceTimer = $timeout(function() {
        $scope.filterMaterials();
      }, 300);
    }
  });
});

修改后的HTML代码

<input ng-model='filtru' type="text" placeholder="...">
<tbody ng-repeat="material in filteredMateriale">
  <!-- 你的表格内容 -->
</tbody>

为什么这能解决你的问题?

  • 性能提升:过滤逻辑仅在搜索输入变化时执行(还加了防抖,减少计算次数),而不是AngularJS的每个digest循环都重新计算,这对5万条数据来说差异巨大。
  • 结果持久化:过滤后的结果存在$scope.filteredMateriale中,你可以在控制器的其他地方直接使用这个变量,而不是每次都重新过滤。

针对大数据量的额外优化建议

如果5万条数据即使过滤后还是有性能问题,试试这些方法:

  • 后端过滤:把过滤逻辑移到PHP层,前端输入时发送过滤参数给PHP,PHP执行带WHERE条件的SQL查询后返回过滤后的JSON。这样前端不需要加载全部5万条数据,性能会大幅提升。
  • 分页显示:即使过滤后还有上千条数据,分页显示(比如每页50条),只渲染当前页的DOM元素,避免一次性渲染大量节点。
  • 虚拟滚动:使用虚拟滚动库,只渲染当前可见区域的列表项,适合长列表场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:34:38