Angular:使用 ng-repeat 时,用新数据更新 $scope 会导致旧数据保留 [英] Angular: Updating $scope with new data causes old data to remain when using ng-repeat

查看:13
本文介绍了Angular:使用 ng-repeat 时,用新数据更新 $scope 会导致旧数据保留的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个奇怪的问题,我用新数据替换了 $rootScope.data.vehicles 中的值,但我视图中的旧数据点与新数据一起保留了大约一秒钟.

例如,在我用新数组替换 $rootScope.data.vehicles 数组后,我的视图将首先显示 3 个新值,然后显示 3 个旧值.视图在 $rootScope.data.vehicles 上使用 ng-repeat 来显示图块.

大约一秒钟后,视图中不再显示 3 个旧值.

每次间隔触发时,我都会得到新值,然后是旧值,即使这些值没有改变.

我的控制器和工厂看起来像这样:

(函数(){var VehicleInjectParams = ['$location', 'dataService', '$rootScope', 'VehiclesRefreshService'];var VehiclesController = function ($location, dataService, $rootScope, VehiclesRefreshService) {var vm = 这个;如果($rootScope.data == 未定义)$rootScope.data = {};$rootScope.data.vehicles = [];函数初始化(){数据服务.getVehicles().then(函数(数据){$rootScope.data.vehicles = data.results;}, 函数(错误){var thisError = error.data.message;});VehiclesRefreshService.getValues();};在里面();};VehiclesController.$inject = VehiclesInjectParams;var VehicleRefreshInjectParams = ['$interval', '$rootScope', '$q', 'dataService'];var VehiclesRefreshService = function ($interval, $rootScope, $q, dataService) {var 工厂 = {};factory.getValues = 函数 () {var 间隔 = $interval(function () {数据服务.getVehicles().then(函数(数据){$rootScope.data.vehicles = data.results;}, 函数(错误){var thisError = error.data.message;});}, 10000);};返厂;};VehiclesRefreshService.$inject = VehiclesRefreshInjectParams;angular.module('teleAiDiagnostics').controller('VehiclesController', VehiclesController).factory('VehiclesRefreshService', VehiclesRefreshService);}());

首先加载数组,然后启动 $interval 计时器以每 10 秒刷新一次值.一旦 dataService 返回新的值列表并将它们放入 $rootScope.data.vehicles 中,我就会注意到 6 个磁贴而不是 3 个.一秒钟后,我只剩下 3 个新磁贴.

我的观点是这样的:

<h1>车辆</h1></标题><article class="icon-gallery flexslider"><部分><figure ng-repeat="$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>在线:{{vehicle.online}}</li><li>状态:{{vehicle.status}}</li><li>AllClear:{{vehicle.allClear}}</li></图></节></文章>

关于如何让我的磁贴无缝刷新的任何想法?非常感谢所有帮助.

解决方案

避免 track by $index 当有唯一的属性标识符可以使用时.

<figure ng-repeat=车辆在$parent.data.vehicles track by ̲v̲e̲h̲i̲c̲l̲e̲.̲i̲d̶̲$̶i̶n̶d̶e̶x̶";类=画廊项目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>在线:{{vehicle.online}}</li><li>状态:{{vehicle.status}}</li><li>AllClear:{{vehicle.allClear}}</li></图>

来自文档:

<块引用><块引用>

如果您正在处理具有唯一标识符属性的对象,则应通过此标识符而不是对象实例进行跟踪.如果您稍后重新加载数据,ngRepeat 将不必为它已经呈现的项目重建 DOM 元素,即使集合中的 JavaScript 对象已被新对象替换.对于大型集合,这会显着提高渲染性能.

—AngularJS ng-repeat 指令 API 参考 - 跟踪

I'm having a strange issue where I replace the values in $rootScope.data.vehicles with new data but the old data points on my view remain for about one second alongside the new data.

For instance, right after I replace the $rootScope.data.vehicles array with a new array my view will display the 3 new values first followed by the 3 old values. View is using ng-repeat on $rootScope.data.vehicles to display tiles.

About one second later the 3 old values are no longer displayed in the view.

Each time the interval fires I get new values followed by old values, even if the values have not changed.

My controller and factory look like so:

(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);
}());

First I load the array then I start an $interval timer to refresh the values every 10 seconds. As soon as the dataService returns the new list of values and puts them in $rootScope.data.vehicles I notice the six tiles instead of 3. One second after that I'm left with only the 3 new tiles.

My view looks like so:

<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>

Any ideas as to how to get my tiles to refresh seamlessly? All help is greatly appreciated.

解决方案

Avoid track by $index when there is a unique property identifier to work with.

<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>

From the Docs:

If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.

— AngularJS ng-repeat Directive API Reference - Tracking

这篇关于Angular:使用 ng-repeat 时,用新数据更新 $scope 会导致旧数据保留的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆