ng-repeat中的函数调用了4次(AngularJs)

时间:2015-09-18 11:58:46

标签: javascript angularjs frontend

以下HTML代码使用21部手机填充ul:

<li ng-repeat="phone in phones" ng-class="{'digestTest': countDigestOccurences(phone) }">
  <p>{{phone.snippet}}</p>
</li>

countDigestOccurences是一种JavaScript方法,它使用字典来跟踪每个电话调用countDigestOccurences()的次数。

$scope.countDigestOccurences = function(phone){
  var phoneFound = false;     
  $.each($scope.digestOccurencesPerPhone, function(){
      if(this.phone.id == phone.id){
        phoneFound = true;
        this.occurences++;
      }
  });

  if(!phoneFound)
  { 
    $scope.digestOccurencesPerPhone.push({
      phone: phone,
      occurences: 1
    });
  }
}

通过这种方法,我可以清楚地看到countDigestOccurences被称为每部手机4次。 我不能,为了我的生活,弄清楚为什么它被称为4次。

enter image description here

更新

即使电话项目的HTML如下所示,周期数仍为4:

    <li ng-repeat="phone in phones "
        class="thumbnail phone-listing" ng-class="{ 'digestTest': countDigestOccurences(phone),  'digestTestAgain': randomMethodDoesNothing() }">
      <p>{{phone.snippet}}</p>
    </li>

2 个答案:

答案 0 :(得分:4)

当Angular在视图上编译并查看表达式时,如ng-class="function()"ng-model="toto",会为其创建$watch。在每个摘要周期,通过脏检查评估手表以确定模型是否有任何变化。

所以在你的ng-repeat中,你有:电话收集中的一个观察者,每个电话实例上的一个观察者和该功能上的一个观察者。由于视图上的函数不是范围变量,因此angular无法知道函数的结果是否已更改(您可能会影响函数中的其他范围变量),因此,它会重新评估每个摘要周期的函数结果

所以你有手机+手机+功能+最后一个消化周期来验证它是否正常:4个周期

一个好的做法是在视图中不使用函数,除非极少数情况。而是将函数的结果存储在范围变量中,并在视图中呈现此变量。

更新:

由于下面的讨论,请注意只为ng-class指令创建了一个watch,它对应于ng-class的值。即,有: ng-class="{'toto' : functionOne(), 'titi' : functionTwo()}",手表已开启:{'toto' : functionOne(), 'titi' : functionTwo()}。 从AngularJs指令代码发出:scope.$watch(attr[name], ngClassWatchAction, true);

答案 1 :(得分:0)

你通过$ http有多少次ajax电话?他们每个人都会触发$ digest。此外,如果某些内容发生了变化(并且有新的数据到达),则会运行另一个$ digest以确保它涵盖所有内容。

为避免这种情况,在父元素的ng-if上添加一个布尔值,并在所有ajax调用到达后将其设置为true(参见$q)。