在ng-repeat中的angular无限$digest循环

28 浏览
0 Comments

在ng-repeat中的angular无限$digest循环

我想在ng-repeat属性中调用函数,这是我的代码\n示例plnkr\nhtml\n


    {{item.val}}
    {{item.abs}}
    {{item.rel}}
    {{item.cum}}

\njs\n

$scope.getGroupedRange = function() {
    return [
      {
        val: 1,
        abs: 1,
        rel: 1,
        cum: 1,
        id: 123456
      }
    ];
  };

\n当我打开控制台时,我注意到了错误\n

10 $digest() 迭代达到。中止!
过去5次迭代触发的观察者:[[{"msg":"fn: function (c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}","newVal":9,"oldVal":8}],[{"msg":"fn: function (c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}","newVal":10,"oldVal":9}],[{"msg":"fn: function (c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}","newVal":11,"oldVal":10}],[{"msg":"fn: function (c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}","newVal":12,"oldVal":11}],[{"msg":"fn: function (c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}","newVal":13,"oldVal":12}]]

\n我的代码的主要目标是在每个事件循环中使用ng-repeat中的函数来计算数据。

0
0 Comments

问题的原因是在ng-repeat中使用了一个函数,这导致了一个无限的$digest循环。解决方法是将函数的返回值存储在一个变量中,并在每次循环中检查前一个返回值是否与当前返回值相同,如果相同则返回前一个返回值。

使用函数在ng-repeat中的一个坏习惯。但是在Angular世界中,你总是可以找到一种方式来伤害自己。

你为什么认为在ng-repeat中使用函数是一个坏习惯?

我并不认为在ng-repeat中使用函数是一个坏习惯。相反,它与函数式编程非常契合。另一方面,这里的讨论显示了Angular与函数式编程的不兼容之处。

如何在改变成员并稍后返回它是函数式的呢?哈哈

0
0 Comments

Angular在数据变化时会自动计算并在模板中显示。但是通过将ng-repeat='item in getGroupedRange()'放入无限循环的重新计算中,会导致无限$digest循环。

通过将列表中可能会被$scope.getGroupedRange函数以任何方式更改的项的值分配给某个作用域变量,比如$scope.range,然后在ng-repeat中对其进行迭代,可以避免这种情况。

在控制器中:

$scope.getGroupedRange = function() {
    $scope.range =  [
      {
        val: 1,
        abs: 1,
        rel: 1,
        cum: 1,
        id: 123456
      }
    ];
  };

在模板中:

<div ng-repeat='item in range track by item.id'>
    <span>{{item.val}}</span>
    <span>{{item.abs}}</span>
    <span>{{item.rel}}</span>
    <span>{{item.cum}}</span>
  </div>

我应该在什么时候调用getGroupedRange函数?我不想在每个地方都粘贴getGroupedRange()...谢谢。

当你需要的时候调用它。

我不想重复自己。

只有在数组中有相似项时才需要使用track by,它不会影响我们正在解决的其他部分。

0
0 Comments

问题的出现的原因是在ng-repeat中使用了一个函数。Angular在digest loop中使用严格的对象比较来确定属性的值是否自上次检查以来发生了变化。因此,每次调用getGroupedRange函数时,它都会返回一个新的值(新数组)。Angular不知道这个情况,并且认为这个值是不稳定的,因此继续检查。但是它在进行了10次检查后中止。

解决方法是构建一个必要的数组,并将其赋值给作用域属性,以便在digest loop期间不会改变:

$scope.groupedRange = $scope.getGroupedRange();

然后在ngRepeat中使用它:

{{item.val}} {{item.abs}} {{item.rel}} {{item.cum}}

因此,使用track by是没有意义的吗?

不,track by解决了与这个问题无关的其他问题。

当然,我只是指我的情况。

ng是如何确定getGroupedRange返回新值的?

它将前一个值(上一次检查时的值)与新值进行比较。每次调用getGroupedRange()时,它都会返回一个新数组。

比较是使用==吗?

它使用严格的===。但无论如何,getGroupedRange() !== getGroupedRange()。

0