我想重复创建div,这些项是函数返回的对象。但是,以下代码报告错误: 达到10 $ digest()次迭代。中止! jsfiddle在这里:http://jsfiddle.net/BraveOstrich/awnqm/
<body ng-app>
<div ng-repeat="entity in getEntities()">
Hello {{entity.id}}!
</div>
</body>
答案 0 :(得分:189)
简短回答:您真的需要这样的功能还是可以使用属性? http://jsfiddle.net/awnqm/1/
答案很长
为简单起见,我将仅描述您的情况 - 对象数组的ngRepeat。另外,我会省略一些细节。
AngularJS使用dirty checking来检测更改。启动应用程序后,它会为$digest
运行$rootScope
。 $digest
将对scope's hierarchy执行深度优先遍历。所有示波器都有手表列表。每只手表都有最后一个值(最初为initWatchVal
)。对于所有监视$digest
运行它的每个范围,获取当前值(watch.get(scope)
)并将其与watch.last
进行比较。如果当前值不等于watch.last
(始终用于第一次比较)$digest
将dirty
设置为true
。如果dirty == true
$digest
从$rootScope
开始另一次深度优先遍历,则会处理所有范围。当脏== false或遍历次数== 10时$digest
结束。在后一种情况下,错误“10 $ digest()迭代达到。”将被记录。
现在关于ngRepeat
。对于每个watch.get
调用,它将来自集合的对象(返回值getEntities
)与缓存中的其他信息(HashQueueMap
hashKey
)一起存储。对于每个watch.get
调用ngRepeat
尝试通过其hashKey
从缓存中获取对象。如果缓存中不存在,ngRepeat
将其存储在缓存中,创建新范围,将对象放在其上,创建DOM元素etc。
现在关于hashKey
。通常hashKey
是由nextUid()
生成的唯一编号。但它可以是function。生成以供将来使用后,hashKey
存储在对象中。
为什么您的示例会生成错误:function getEntities()
始终返回带有新对象的数组。此对象没有hashKey
,并且在ngRepeat
缓存中不存在。因此,每个ngRepeat
上的watch.get
会为{{entity.id}}
的新监视为其创建新范围。第一个watch.get
上的此手表有watch.last == initWatchVal
。所以watch.get() != watch.last
。所以$digest
开始新的遍历。所以ngRepeat
使用新手表创建新范围。所以...经过10次遍历后,你会收到错误。
如何修复
getEntities()
来电时创建新对象。hashKey
方法。有关示例,请参阅this topic。希望知道AngularJS内部人员的人在我出错的时候会纠正我。
答案 1 :(得分:42)
在重复
之外初始化数组<body ng-app>
<div ng-init="entities = getEntities()">
<div ng-repeat="entity in entities">
Hello {{entity.id}}!
</div>
</div>
</body>
答案 2 :(得分:15)
这是reported here并得到了回应:
您的getter不是幂等的并且更改模型(通过每次调用时生成一个新数组)。这迫使角度继续调用它,希望模型最终会稳定,但它永远不会这样,角度放弃并抛出异常。
getter返回的值相等但不相同,这就是问题所在。
如果将阵列移出主控制器,您可以看到此行为消失:
var array = [{id:'angularjs'}];
function Main($scope) {
$scope.getEntities = function(){return array;};
};
因为现在它每次都返回相同的对象。您可能需要重新设计模型以使用范围上的属性而不是函数:
我们通过将控制器方法的结果分配给属性来解决它,然后对它进行重复:重复它。
答案 3 :(得分:7)
基于@przno评论
<body ng-app>
<div ng-repeat="item in t = angular.equals(t, getEntities()) ? t : getEntities()">
Hello {{item.id}}!
</div>
</body>
BTW第二个解决方案@Artem Andreev建议不使用Angular 1.1.4及更高版本,而第一个解决方案并不能解决问题。所以,我现在担心这是一个不那么尖刻的解决方案而没有功能上的缺点