Javascript 角度:使用新数据更新$scope会导致在使用ng repeat时保留旧数据

Javascript 角度:使用新数据更新$scope会导致在使用ng repeat时保留旧数据,javascript,angularjs,arrays,angularjs-scope,Javascript,Angularjs,Arrays,Angularjs Scope,我遇到了一个奇怪的问题,我用新数据替换$rootScope.data.vehicles中的值,但视图中的旧数据点与新数据一起保留了大约一秒钟 例如,在我用新数组替换$rootScope.data.vehicles数组之后,我的视图将首先显示3个新值,然后显示3个旧值。视图正在$rootScope.data.vehicles上使用ng repeat显示分幅 大约一秒钟后,3个旧值不再显示在视图中 每次触发间隔时,我都会得到新值,后面跟着旧值,即使这些值没有更改 我的控制器和工厂看起来是这样的

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

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

大约一秒钟后,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);
}());
首先加载数组,然后启动$interval计时器,每10秒刷新一次值。一旦dataService返回新的值列表并将它们放入$rootScope.data.vehicles中,我就会注意到六个tile,而不是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>

车辆
  • {{vehicle.id}
  • {{vehicle.ip}
  • 联机:{{vehicle.Online}
  • 状态:{{vehicle.Status}
  • AllClear:{{vehicle.AllClear}}

关于如何让我的互动程序无缝刷新,有什么想法吗?非常感谢您的帮助。

迈克·费尔特曼在上述评论中解决了这个问题。只需将“trackby$index”添加到视图中的ng repeat标记中即可。请看这里:

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

车辆
  • {{vehicle.id}
  • {{vehicle.ip}
  • 联机:{{vehicle.Online}
  • 状态:{{vehicle.Status}
  • AllClear:{{vehicle.AllClear}}

希望这篇文章能帮助将来遇到同样问题的人。

迈克·费尔特曼在上面的评论中解决了这个问题。只需将“trackby$index”添加到视图中的ng repeat标记中即可。请看这里:

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

车辆
  • {{vehicle.id}
  • {{vehicle.ip}
  • 联机:{{vehicle.Online}
  • 状态:{{vehicle.Status}
  • AllClear:{{vehicle.AllClear}}

希望这篇文章能帮助将来遇到同样问题的人。

IIRC看到vehicles数组已更改并立即渲染,然后进行清理。将track by$index添加到ng repeat应该基本上强制每次从第一项开始渲染


我同意另一篇关于$rootScope使用的帖子。如果您试图使车辆在全球范围内可用,而不是将其存储在rootScope中,请将其存储在您的数据服务中,并在必要时将其注入。这将是一种更干净的方法。

IIRC,可以看到车辆阵列已更改,并立即渲染它,然后进行清理。将track by$index添加到ng repeat应该基本上强制每次从第一项开始渲染


我同意另一篇关于$rootScope使用的帖子。如果您试图使车辆在全球范围内可用,而不是将其存储在rootScope中,请将其存储在您的数据服务中,并在必要时将其注入。这将是一种更干净的方法。

当有唯一的属性标识符可供使用时,避免使用
按$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>

  • {{vehicle.id}
  • {{vehicle.ip}
  • 联机:{{vehicle.Online}
  • 状态:{{vehicle.Status}
  • AllClear:{{vehicle.AllClear}}
从文档中:

如果使用具有唯一标识符属性的对象,则应按此标识符而不是对象实例进行跟踪。如果以后重新加载数据,
ngRepeat
将不必为已呈现的项重新构建DOM元素,即使集合中的JavaScript对象已替换为新对象。对于大型集合,这将显著提高渲染性能


当有唯一的属性标识符可使用时,请避免按$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>

  • {{vehicle.id}
  • {{vehicle.ip}
  • 联机:{{vehicle.Online}
  • 状态:{{vehicle.Status}
  • AllClear:{{vehicle.AllClear}}
从文档中:

如果使用具有唯一标识符属性的对象,则应按此标识符而不是对象实例进行跟踪。如果以后重新加载数据,
ngRepeat
将不必为已呈现的项重新构建DOM元素,即使集合中的JavaScript对象已替换为新对象。对于大型集合,这将显著提高渲染性能


只是一种预感,但试着将track by$index添加到ng repeat中。此外,我认为,如果每次迭代都更新数组,而不是覆盖所有值,那么您的界面就会显得不那么紧张和干净。那么为什么要使用
$rootScope
?我认为使用
$scope
将使您的代码更具可读性和可管理性。还有,什么是
dataService
,它做什么?迈克·费尔特曼你是赢家!这绝对解决了我的问题。非常感谢。我想你应该把这个贴出来作为这个问题的答案,我会这样做的。太棒了。我看到你已经添加了它作为答案。只是一种预感,但试着将track by$index添加到你的ng repeat中。还有,我不知道