【问题标题】:AngularJS InfDig error (infinite loop) with ng-repeat function that returns array of objects带有返回对象数组的ng-repeat函数的AngularJS InfDig错误(无限循环)
【发布时间】:2014-01-05 11:57:19
【问题描述】:

这是我的代码:

<h1 ng-repeat="item in func()">something</h1>

$scope.func = function(){
  return [{"property" : "value1"},{"property": "value2"}];
}

在 Angular.js v. 1.1.1 中没有错误。在 Angular.JS v 1.2.1 我得到一个 infDig 错误。

Fiddle of v.1.1.1

Fiddle of v.1.2.1

你能解释一下这种情况吗?非常感谢。

【问题讨论】:

标签: angularjs angularjs-ng-repeat infinite-loop angularjs-infdig


【解决方案1】:

从 AngularJS 1.2 开始:“track by”表达式被添加到 ng-repeat 中,更恰当地解决了这个问题,如图所示 在下面的代码中。

<h1 ng-repeat="item in func() track by $index">something</h1>

$scope.func = function(){
  return [{"property" : "value1"},{"property": "value2"}];
}

以下文章有助于更详细地了解该表达式以及它为何如此有用,尤其是在处理 $$haskey Using Track-By With ngRepeat In AngularJS 1.2 by Ben Nadal 时。

问题在于您每次都在创建一个新数组,因此 Angular 需要跟踪新的东西。据我所知,ng-repeat 运行,然后立即再次检查它的集合以查看该循环中是否有任何变化。因为该函数返回一个新数组,这被认为是一个变化。

看看这个:http://jsfiddle.net/kL5YZ/ 如果您查看console.log 并单击按钮,您将看到对象的$$hashKey 属性在每次运行ng-repeat 时都在更改。

更改从 1.1.4 版本开始,但更改日志没有提供任何关于行为不同的线索。新行为对我来说确实更有意义。

我找到了一篇很棒的帖子,深入解释了当前的行为:How to Loop through items returned by a function with ng-repeat?

如果您确保每次都返回相同的对象/数组,则不会出现错误。您可以让函数缓存它根据参数创建的任何内容,并在传入这些参数时始终返回相同的数组/对象。因此,myFunc('foo') 将始终返回相同的数组,而不是看起来像相同的。请参阅下面我的代码中的注释。 Live demo (click).

<div ng-repeat="foo in foos">
  <div ng-repeat="bar in barFunc(foo)">{{bar.text}}</div>
  <div ng-repeat="bar in barFunc('test')">{{bar.text}}</div>
</div>

JavaScript:

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope, myService) {
  $scope.foos = [
    'a','b','c'
  ];
  //I put this into a service to avoid cluttering the controller
  $scope.barFunc = myService.getObj;
});

app.factory('myService', function() {
  /*
   * anything created will be stored in this cache object,
   * based on the arguments passed to `getObj`.
   * If you need multiple arguments, you could form them into a string,
   * and use that as the cache key
   * since there's only one argument here, I'll just use that
   */
  var cache = {};

  var myService = {
    getObj : function(val) {
      //if we haven't created an array with this argument before
      if (!cache[val]) {
        //create one and store it in the cache with that argument as the key
        cache[val] = [
          {text:val}
        ];
      }
      //return the cached array
      return cache[val];
    }
  };

  return myService;
});

【讨论】:

  • 谢谢。但是如果我需要将参数传递给这个函数怎么办:&lt;h1 ng-repeat="item in func(dynamicParameter)"&gt;something&lt;/h1&gt;
  • @user3162402 我用通用但完整的解决方案更新了我的答案。我还在 SO 上找到了一篇非常好的帖子,关于 ng-repeat 与函数一起工作的方式,但我仍然不知道为什么它曾经工作过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
相关资源
最近更新 更多