2017-08-01 85 views
0

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

例如,在我用新数组替换$ rootScope.data.vehicles数组后,我的视图会先显示3个新值,然后是3个旧值。 View正在使用ng-repeat在$ rootScope.data.vehicles上显示切片。

immediately after replacing array

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

one second after replacing array

每次时间间隔触发我得到其次是旧值新值,即使值都没有改变。

interval continues to refresh

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

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

任何想法,如何让我的瓷砖无缝刷新?所有的帮助非常感谢。

+1

只是一种预感,而是尝试通过$指数将跟踪你的NG-重复。另外,如果你实际上用每次迭代来更新数组,而不是覆盖所有的值,我认为你的界面看起来会更少跳跃和更清晰。 –

+2

那么你为什么使用'$ rootScope'?我认为使用'$ scope'只会让你的代码更具可读性和可管理性。另外,什么是'dataService',它有什么作用? –

+0

Mike Feltman你是赢家!这绝对解决了我的问题。太感谢了。我认为你应该将此作为这个问题的答案发布,并且将其标记为这样。 – Ian

回答

2

当存在唯一的属性标识符以处理时,请避免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对象已被替换为新元素。对于大型集合,这显着提高了渲染性能。

— AngularJS ng-repeat Directive API Reference - Tracking

+0

谢谢你的抬头。更新了我所有'track by'语句以在对象上使用唯一ID。目前效果很好。 – Ian

1

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> 

希望这篇文章将有助于在未来遇到同样类型的问题的人。

0

IIRC,内部Angular发现车辆阵列发生了变化并立即呈现,然后清理干净。通过$ index添加轨道到ng-repeat基本上应该强制渲染从每一次的第一项开始。

我确实同意另一篇关于使用$ rootScope的文章。如果您试图使车辆在全球范围内可用,而不是将其存储在rootScope中,请将它们存储在数据服务中,并在需要时进行注入。这将是一个更清洁的方法。

+0

感谢您的提示。我已经从$ rootScope中删除了它们。 – Ian