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

在AngularJS Material中用md-virtual-repeat实现无限滚动遇阻

解决AngularJS Material VirtualRepeat使用本地数组的问题

我仔细看了你的代码,问题核心在于误把同步的本地数组当成异步Promise处理,同时infiniteItems对象的初始化和方法逻辑没有适配本地数据的场景。下面是修正后的完整解决方案:

核心问题梳理

  • 你原代码的fetchMoreItems_里还在调用$scope.items.then(),但$scope.items已经是现成的数组,并非$http返回的Promise,这会直接导致代码报错。
  • infiniteItems内部的items属性没有初始化为你的本地数组,导致getItemAtIndex找不到对应数据。
  • getLength的逻辑错误,应该返回数据的真实总长度,而不是动态计算的numLoaded_ +5,否则虚拟滚动会一直认为还有更多数据需要加载。

修正后的完整代码

(function () { 
  'use strict'; 

  angular 
    .module('infiniteScrolling', ['ngMaterial']) 
    .controller('AppCtrl', function ($timeout,$scope) { 
      // 本地数据源数组
      $scope.items = [ 
        { "categoryId": "cat1", "id": "pack0" }, 
        { "categoryId": "cat1", "id": "pack8" }, 
        { "categoryId": "cat1", "id": "pack9" }, 
        { "categoryId": "cat1", "id": "pack10" }, 
        { "categoryId": "cat1", "id": "pack11" },
        // 可添加更多数据测试滚动效果
        { "categoryId": "cat1", "id": "pack12" },
        { "categoryId": "cat1", "id": "pack13" },
        { "categoryId": "cat1", "id": "pack14" },
        { "categoryId": "cat1", "id": "pack15" },
        { "categoryId": "cat1", "id": "pack16" },
        { "categoryId": "cat1", "id": "pack17" }
      ]; 

      var vm = this; 
      vm.infiniteItems = { 
        numLoaded_: 0,
        batchSize: 5, // 每次分批加载的数量
        items: angular.copy($scope.items), // 初始化本地数据源

        // 必填方法:返回指定索引的项
        getItemAtIndex: function (index) { 
          // 若当前已加载数量不足,触发加载更多
          if (index >= this.numLoaded_ && this.numLoaded_ < this.items.length) {
            this.fetchMoreItems_();
          }
          // 超出总数据长度时返回null
          if (index >= this.items.length) return null;
          return this.items[index]; 
        }, 

        // 必填方法:返回数据总长度
        getLength: function () { 
          return this.items.length; 
        }, 

        // 模拟分批加载逻辑(本地数据可同步更新,这里用$timeout模拟异步延迟体验)
        fetchMoreItems_: function () { 
          // 避免重复加载
          if (this.numLoaded_ >= this.items.length) return;
          
          $timeout(angular.bind(this, function () {
            // 计算本次加载数量,不超过剩余数据量
            var loadCount = Math.min(this.batchSize, this.items.length - this.numLoaded_);
            this.numLoaded_ += loadCount;
          }), 500);
        } 
      }; 
    }); 
})();

关键修改点说明

  1. 初始化数据源:把本地的$scope.items赋值给vm.infiniteItems.items,确保数据来源正确。
  2. 修正长度计算:getLength直接返回数组总长度,让virtualRepeat明确知道数据边界。
  3. 重构加载逻辑:去掉错误的Promise调用,用$timeout模拟异步加载的流畅体验(不需要延迟的话可以直接同步更新numLoaded_),同时增加边界判断防止重复加载。
  4. 优化索引判断:在getItemAtIndex里增加超出总长度的判断,返回null避免报错。

这样修改后,virtualRepeat就能正确基于控制器内的本地JSON数组实现无限滚动,逻辑和官方示例对齐,但完全适配了同步数据源的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:08:33