Angular:使用新数据更新$ scope会导致旧数据在使用ng-repeat时保留
我遇到一个奇怪的问题,那就是用新数据替换了$ rootScope.data.vehicles中的值,但我的旧数据点视图与新数据一起保持约一秒钟。
例如,在我用新数组替换$ rootScope.data.vehicles数组后,我的视图会先显示3个新值,然后是3个旧值。 View正在使用ng-repeat在$ rootScope.data.vehicles上显示切片。
约一秒钟后,3个旧值在视图中不再显示。
每次时间间隔触发我得到其次是旧值新值,即使值都没有改变。
我的控制器和工厂看起来像这样:
(function() {
var vehiclesInjectParams = ['$location', 'dataService', '$rootScope', 'VehiclesRefreshService'];
var VehiclesController = function ($location, dataService, $rootScope, VehiclesRefreshService) {
var vm = this;
if ($rootScope.data == undefined)
$rootScope.data = {};
$rootScope.data.vehicles = [];
function init() {
dataService.getVehicles()
.then(function (data) {
$rootScope.data.vehicles = data.results;
}, function (error) {
var thisError = error.data.message;
});
VehiclesRefreshService.getValues();
};
init();
};
VehiclesController.$inject = vehiclesInjectParams;
var vehiclesRefreshInjectParams = ['$interval', '$rootScope', '$q', 'dataService'];
var VehiclesRefreshService = function ($interval, $rootScope, $q, dataService) {
var factory = {};
factory.getValues = function() {
var interval = $interval(function() {
dataService.getVehicles()
.then(function (data) {
$rootScope.data.vehicles = data.results;
}, function (error) {
var thisError = error.data.message;
});
}, 10000);
};
return factory;
};
VehiclesRefreshService.$inject = vehiclesRefreshInjectParams;
angular.module('teleAiDiagnostics').controller('VehiclesController', VehiclesController).factory('VehiclesRefreshService', VehiclesRefreshService);
}());
首先我加载阵列然后我启动$间隔定时器,刷新值每隔10秒。只要dataService返回新的值列表并将它们放入$ rootScope.data.vehicles中,我会注意到六个贴图,而不是3个。之后,我只剩下3个新的贴图。
我的观点看起来像这样:
<header>
<h1>Vehicles</h1>
</header>
<article class="icon-gallery flexslider">
<section>
<figure ng-repeat="vehicle in $parent.data.vehicles" class="gallery-item svg">
<a class="nextpage" ng-href="#!/vehicle/{{vehicle.vehicleID}}">
<img src="img/machine/01.svg" alt="">
<span class="green-machine-code">{{vehicle.id}}</span>
</a>
<ul>
<li>{{vehicle.id}}</li>
<li>{{vehicle.ip}}</li>
<li>Online: {{vehicle.online}}</li>
<li>Status: {{vehicle.status}}</li>
<li>AllClear: {{vehicle.allClear}}</li>
</ul>
</figure>
</section>
</article>
任何想法,如何让我的瓷砖无缝刷新?所有的帮助非常感谢。
当存在唯一的属性标识符以处理时,请避免track by $index
。
<figure ng-repeat="vehicle in $parent.data.vehicles track by ̲v̲e̲h̲i̲c̲l̲e̲.̲i̲d̲ ̶$̶i̶n̶d̶e̶x̶" class="gallery-item svg">
<a class="nextpage" ng-href="#!/vehicle/{{vehicle.vehicleID}}">
<img src="img/machine/01.svg" alt="">
<span class="green-machine-code">{{vehicle.id}}</span>
</a>
<ul>
<li>{{vehicle.id}}</li>
<li>{{vehicle.ip}}</li>
<li>Online: {{vehicle.online}}</li>
<li>Status: {{vehicle.status}}</li>
<li>AllClear: {{vehicle.allClear}}</li>
</ul>
</figure>
从文档:
如果您使用的是具有唯一标识符属性对象时,你应该通过这个标识符,而不是对象实例跟踪。如果稍后重新加载数据,
ngRepeat
将不必为其已经呈现的项目重建DOM元素,即使集合中的JavaScript对象已被替换为新元素。对于大型集合,这显着提高了渲染性能。
谢谢你的抬头。更新了我所有'track by'语句以在对象上使用唯一ID。目前效果很好。 – Ian
Mike Feltman在上述评论中解决了这个问题。这非常简单,只需在视图中为ng-repeat标记添加'track by $ index'即可。看到这里:
<header>
<h1>Vehicles</h1>
</header>
<article class="icon-gallery flexslider">
<section>
<figure ng-repeat="vehicle in $parent.data.vehicles track by $index" class="gallery-item svg">
<a class="nextpage" ng-href="#!/vehicle/{{vehicle.vehicleID}}">
<img src="img/machine/01.svg" alt="">
<span class="green-machine-code">{{vehicle.id}}</span>
</a>
<ul>
<li>{{vehicle.id}}</li>
<li>{{vehicle.ip}}</li>
<li>Online: {{vehicle.online}}</li>
<li>Status: {{vehicle.status}}</li>
<li>AllClear: {{vehicle.allClear}}</li>
</ul>
</figure>
</section>
</article>
希望这篇文章将有助于在未来遇到同样类型的问题的人。
IIRC,内部Angular发现车辆阵列发生了变化并立即呈现,然后清理干净。通过$ index添加轨道到ng-repeat基本上应该强制渲染从每一次的第一项开始。
我确实同意另一篇关于使用$ rootScope的文章。如果您试图使车辆在全球范围内可用,而不是将其存储在rootScope中,请将它们存储在数据服务中,并在需要时进行注入。这将是一个更清洁的方法。
感谢您的提示。我已经从$ rootScope中删除了它们。 – Ian
只是一种预感,而是尝试通过$指数将跟踪你的NG-重复。另外,如果你实际上用每次迭代来更新数组,而不是覆盖所有的值,我认为你的界面看起来会更少跳跃和更清晰。 –
那么你为什么使用'$ rootScope'?我认为使用'$ scope'只会让你的代码更具可读性和可管理性。另外,什么是'dataService',它有什么作用? –
Mike Feltman你是赢家!这绝对解决了我的问题。太感谢了。我认为你应该将此作为这个问题的答案发布,并且将其标记为这样。 – Ian