AngularJS InfDig 错误(无限循环),带有返回对象数组的 ng-repeat 函数 [英] AngularJS InfDig error (infinite loop) with ng-repeat function that returns array of objects

查看:26
本文介绍了AngularJS InfDig 错误(无限循环),带有返回对象数组的 ng-repeat 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码:

<h1 ng-repeat="func() 中的项目">something</h1>$scope.func = function(){return [{"property" : "value1"},{"property": "value2"}];}

在 Angular.js v. 1.1.1 中没有错误.在 Angular.JS v 1.2.1 中,我遇到了 infDig 错误.

v.1.1.1 的小提琴

v.1.2.1 的小提琴

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

解决方案

从 AngularJS 1.2 开始:track by"表达式被添加到 ng-repeat 中,更合适地解决了这个问题,如演示在下面的代码中.

以下文章有助于更详细地理解该表达式以及它为何如此有用,尤其是在处理 $$haskey 在 AngularJS 1.2 中使用 Track-By 和 ngRepeat 由 Ben Nadal 撰写.

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

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

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

这是我发现的一篇很好的帖子,它深入解释了当前的行为:如何使用 ng-repeat 循环遍历函数返回的项目?

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

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

JavaScript:

var app = angular.module('myApp', []);app.controller('myCtrl', function($scope, myService) {$scope.foos = ['a','b','c'];//我把它放到一个服务中以避免混乱控制器$scope.barFunc = myService.getObj;});app.factory('myService', function() {/** 创建的任何内容都将存储在此缓存对象中,* 基于传递给 `getObj` 的参数.* 如果你需要多个参数,你可以将它们组成一个字符串,* 并将其用作缓存键* 因为这里只有一个参数,我就用那个*/var 缓存 = {};var myService = {getObj : 函数(val) {//如果我们之前没有用这个参数创建过一个数组如果(!缓存[val]){//创建一个并将其以该参数作为键存储在缓存中缓存[val] = [{文本:val}];}//返回缓存的数组返回缓存[val];}};返回我的服务;});

Here's my code:

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

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

In Angular.js v. 1.1.1 there's no mistake. In Angular.JS v 1.2.1 I get an infDig mistake.

Fiddle of v.1.1.1

Fiddle of v.1.2.1

Could you explain this situation? Thanks a lot.

解决方案

As of AngularJS 1.2: The "track by" expression was added to ng-repeat and more appropriately addresses this issue as demonstrated in the following code.

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

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

The following article helps understand the expression in more detail and why it is so useful, particularly when dealing with $$haskey Using Track-By With ngRepeat In AngularJS 1.2 by Ben Nadal.

The problem is that you're creating a new array each time, so it's something new that angular needs to track. As far as I can tell, ng-repeat runs, then immediately checks its collection again to see if anything changed in that cycle. Because the function returns a new array, that is perceived as a change.

Check this out: http://jsfiddle.net/kL5YZ/. If you look in the console.log and click the button, you will see that the $$hashKey property of the objects is being changed each time ng-repeat runs.

The change occurs starting at version 1.1.4, but the changelog doesn't give any clues as to why the behavior is different. The new behavior does make more sense to me.

Here's a great post I found explaining the current behavior in depth: How to Loop through items returned by a function with ng-repeat?

If you make sure to return the same object/array each time, you won't have the error. You could have the function cache anything it creates based on the arguments and always return the same array/object when those arguments are passed in. So, myFunc('foo') will always return the same array, not a new one that looks the same. See the notes in my code below. 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;
});

这篇关于AngularJS InfDig 错误(无限循环),带有返回对象数组的 ng-repeat 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆