在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); } }; }); })();
关键修改点说明
- 初始化数据源:把本地的
$scope.items赋值给vm.infiniteItems.items,确保数据来源正确。 - 修正长度计算:
getLength直接返回数组总长度,让virtualRepeat明确知道数据边界。 - 重构加载逻辑:去掉错误的Promise调用,用
$timeout模拟异步加载的流畅体验(不需要延迟的话可以直接同步更新numLoaded_),同时增加边界判断防止重复加载。 - 优化索引判断:在
getItemAtIndex里增加超出总长度的判断,返回null避免报错。
这样修改后,virtualRepeat就能正确基于控制器内的本地JSON数组实现无限滚动,逻辑和官方示例对齐,但完全适配了同步数据源的场景。
内容的提问来源于stack exchange,提问作者Andy Mummau
相关产品推荐
相关产品推荐

