关于angularjs:如何循环使用ng-repeat函数返回的项目?

How to Loop through items returned by a function with ng-repeat?

我想重复创建div,项是由函数返回的对象。但是,以下代码报告错误:已达到10$digest()个迭代。中止!jspiddle在这里:http://jspiddle.net/braveostrich/awnqmrich/

1
2
3
4
5
<body ng-app>
 
    Hello {{entity.id}}!
 
</body>

简短的回答:你真的需要这样的功能还是可以使用属性?http://jsfiddle.net/awnqm/1/

长回答

为了简单起见,我将只描述您的情况—ngrepeat用于对象数组。另外,我将省略一些细节。

AngularJS使用脏检查来检测更改。当应用程序启动时,它为$rootScope运行$digest$digest将对作用域的层次结构进行深度优先遍历。所有范围都有手表列表。每个表都有最后一个值(最初是initWatchVal)。对于所有手表的每个范围,$digest运行它,获取当前值(watch.get(scope)并将其与watch.last进行比较。如果当前值不等于watch.last(总是用于第一次比较),$digestdirty设置为true。当处理所有作用域时,如果dirty == true$digest$rootScope开始另一个深度首次遍历。当脏=假或遍历数=10时,$digest结束。在后一种情况下,将记录错误"10$digest()iterations reached."。

关于ngRepeat。对于每个watch.get调用,它存储来自集合的对象(返回值getEntities)以及缓存中的附加信息(HashQueueMap,由hashKey)。对于每个watch.get调用ngRepeat尝试从缓存中通过其hashKey获取对象。如果它不存在于缓存中,那么ngRepeat将它存储在缓存中,创建新的作用域,将对象放在上面,创建dom元素等。

关于hashKey。通常,hashKeynextUid()生成的唯一数。但它可以发挥作用。生成后将hashKey存储在对象中,以备将来使用。

示例生成错误的原因:函数getEntities()总是返回带有新对象的数组。此对象没有hashKey,并且不存在于ngRepeat缓存中。因此,每个watch.get上的ngRepeat为它生成了新的范围,并为{{entity.id}}生成了新的监视。这只手表上的第一只watch.getwatch.last == initWatchVal。因此,watch.get() != watch.last。因此,$digest开始新的导线测量。因此,ngRepeat用新手表创造了新的范围。所以…经过10次遍历后,您会得到错误。

如何修复它

  • 不要在每个getEntities()调用上创建新对象。
  • 如果需要创建新对象,可以为它们添加hashKey方法。有关示例,请参阅本主题。
  • 希望了解安古拉吉斯内在的人会纠正我的错误。


    在重复之外初始化数组

    1
    2
    3
    4
    5
    6
    7
    <body ng-app>
       
           
               Hello {{entity.id}}!
           
       
    </body>


    这里报告了这一点,并得到了以下回复:

    Your getter is not idempotent and changes the model (by generating a new array each time it is called). This is forcing angular to keep on calling it in hope that the model will eventually stabilize, but it never does so angular gives up and throws an exception.

    The values the getter return are equal but not identical and that's the problem.

    < /块引用>

    如果将数组移到主控制器之外,可以看到此行为消失:

    1
    2
    3
    4
    var array = [{id:'angularjs'}];
    function Main($scope) {
        $scope.getEntities = function(){return array;};
    };

    因为现在它每次返回相同的对象。您可能需要重新设计您的模型,以便在作用域上使用属性而不是函数:

    We worked around it by assigning the result of the controller's method to a property, and doing ng:repeat against it.

    < /块引用>


    基于@przno评论

    1
    2
    3
    4
    5
    <body ng-app>
     
        Hello {{item.id}}!
     
    </body>

    btw第二个解决方案@artem andreev建议在角度为1.1.4或更大的情况下不工作,而第一个解决方案无法解决问题。所以,现在恐怕这是一个不那么尖锐的解决方案,功能上没有缺点