如何循环ng-repeat函数返回的项目?
我想重复创builddiv,这些项目是由函数返回的对象。 但是,以下代码报告错误:已达到10 $ digest()迭代。 中止! jsfiddle在这里: http : //jsfiddle.net/BraveOstrich/awnqm/
<body ng-app> <div ng-repeat="entity in getEntities()"> Hello {{entity.id}}! </div> </body>
简短的回答 :你真的需要这样的function,或者你可以使用财产? http://jsfiddle.net/awnqm/1/
长答案
为了简单起见,我只描述你的情况 – 对象数组的ngRepet。 另外,我会省略一些细节。
AngularJS使用脏检查来检测变化。 当应用程序启动时,它为$rootScope
运行$digest
。 $digest
将对作用域的层次结构进行深度优先遍历。 所有范围都有手表列表。 每个手表都有最后一个值(最初是initWatchVal
)。 对于所有手表的$digest
运行它,获取当前值( watch.get(scope)
),并将其与watch.last
进行比较。 如果当前值不等于watch.last
(始终用于第一次比较) $digest
将dirty
设置为true
。 当所有的作用域被处理时,如果dirty == true
$digest
从$rootScope
开始另一个深度优先遍历。 $digest
在dirty == false或遍历数为10时结束。在后一种情况下,错误“10 $ digest()迭代到达”。 将被logging。
现在关于ngRepeat
。 对于每个watch.get
调用它存储集合中的对象(返回getEntities
值)与caching中的HashQueueMap
信息(通过hashKey
)。 对于每个watch.get
调用ngRepeat
尝试通过其caching中的hashKey
获取对象。 如果在caching中不存在, ngRepeat
将其存储在caching中,创build新的作用域,将对象放在caching中,创buildDOM元素等 。
现在关于hashKey
。 通常hashKey
是由nextUid()
生成的唯一编号。 但它可以是function 。 hashKey
在生成后存储在对象中供将来使用。
为什么你的例子产生错误 :函数getEntities()
总是返回数组与新的对象。 这个对象没有hashKey
,在ngRepeat
caching中不存在。 因此,每个ngRepeat
上的watch.get
为{{entity.id}}
新手表生成新的范围。 第一个watch.get
上的这个表具有watch.last == initWatchVal
。 所以watch.get() != watch.last
。 所以$digest
开始新的遍历。 所以ngRepeat
用新手表创build新的范围。 所以…经过10遍后,你会得到错误。
你如何解决它
- 不要在每个
getEntities()
调用中创build新的对象。 - 如果你需要创build新的对象,你可以为它们添加
hashKey
方法。 看到这个主题的例子。
希望那些认识AngularJS内部的人纠正我,如果我错了什么。
初始化重复之外的数组
<body ng-app> <div ng-init="entities = getEntities()"> <div ng-repeat="entity in entities"> Hello {{entity.id}}! </div> </div> </body>
这是在这里报告 ,得到了这样的回应:
你的getter不是幂等的并且改变模型(每次调用时都会生成一个新的数组)。 这迫使angular度继续调用它,希望模型最终稳定,但它永远不会放弃,并抛出一个例外。
getter返回的值是相等的,但不完全相同,这就是问题所在。
如果将arrays移到主控制器外面,您可以看到这种行为消失:
var array = [{id:'angularjs'}]; function Main($scope) { $scope.getEntities = function(){return array;}; };
因为现在每次都返回相同的对象。 您可能需要重新构build模型,以便在范围内使用属性而不是函数:
我们通过将控制器方法的结果分配给一个属性来解决这个问题,并且对其进行重复。
根据@przno评论
<body ng-app> <div ng-repeat="item in t = angular.equals(t, getEntities()) ? t : getEntities()"> Hello {{item.id}}! </div> </body>
BTW的第二个解决scheme@Artem Andreevbuild议在1.1.4以上版本的Angular中不工作,而第一个解决不了这个问题。 所以,现在我恐怕这是没有缺点的解决scheme