【问题标题】:function inside ng-repeat called 4 times (AngularJs)ng-repeat 中的函数调用了 4 次(AngularJs)
【发布时间】:2015-09-18 11:58:45
【问题描述】:

以下 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 次。

更新:

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

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

【问题讨论】:

标签: javascript angularjs frontend


【解决方案1】:

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

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

所以你有电话 + 电话 + 功能 + 最后一个摘要周期来验证一切是否正常:4 个周期

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

更新:

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

【讨论】:

  • 如果是这样的话,我放在答案底部的代码现在不会增加 4 个周期吗?代码不符合标准,因为这是一个项目测试摘要周期
  • 我不明白为什么你添加的代码会增加 Lucas 的摘要数。
  • 为清楚起见再次更新。我在 ng-class 中引入了一个新函数。这不应该增加另一个观察者,从而增加另一个循环吗?
  • 不,因为您总是在同一个手机实例上工作,即使您添加了 phone.imageUrl、phone.id、... 这是观看的手机对象而不是它的属性
  • 是的,但是我现在添加了另一个功能。根据我的理解,一个函数不需要另一个循环吗?
【解决方案2】:

您通过 $http 进行了多少次 ajax 调用?他们每个人都会触发一个$digest。此外,如果发生了变化(新数据已经到达),另一个 $digest 将运行以确保它涵盖了所有内容。

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

【讨论】:

  • 无,这是静态数据。这是一个弄清楚摘要周期的项目。
  • 静态数据,但在服务器端(API 或 json 文件)。在 UI 上,您通过 HTTP 获取它,因此它变得“动态”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-22
  • 1970-01-01
  • 1970-01-01
  • 2016-03-28
相关资源
最近更新 更多