Angularjs 如何使用ng repeat遍历函数返回的项?
我想重复创建div,项是由函数返回的对象。但是,以下代码会报告错误: 已达到10$digest()迭代次数。流产!JSFIDLE在这里:Angularjs 如何使用ng repeat遍历函数返回的项?,angularjs,Angularjs,我想重复创建div,项是由函数返回的对象。但是,以下代码会报告错误: 已达到10$digest()迭代次数。流产!JSFIDLE在这里: 你好{{entity.id}! 这是一个问题,并得到了以下响应: 您的getter不是幂等的,它会更改模型(每次调用时生成一个新数组)。这迫使angular继续调用它,希望模型最终会稳定下来,但它从未这样做angular放弃并抛出异常 getter返回的值相等但不相同,这就是问题所在 如果将阵列移到主控制器外,则可以看到此行为消失: var数组=[{id:'
你好{{entity.id}!
这是一个问题,并得到了以下响应:
您的getter不是幂等的,它会更改模型(每次调用时生成一个新数组)。这迫使angular继续调用它,希望模型最终会稳定下来,但它从未这样做angular放弃并抛出异常
getter返回的值相等但不相同,这就是问题所在
如果将阵列移到主控制器外,则可以看到此行为消失:
var数组=[{id:'angularjs'}];
主要功能($scope){
$scope.getEntities=function(){return array;};
};
因为现在它每次都返回相同的对象。您可能需要重新构建模型,以使用作用域上的属性而不是函数:
我们通过将控制器方法的结果分配给属性并对其执行ng:repeat来解决这个问题
简短回答:您真的需要这样的功能还是可以使用属性 长答案 为了简单起见,我将只描述您的case-ngRepeat对象数组。另外,我将省略一些细节 AngularJS用于检测更改。当应用程序启动时,它会运行一段时间
$digest
将对进行深度优先遍历。所有示波器都有手表列表。每个手表都有最后一个值(最初为initWatchVal
)。对于所有手表的每个作用域,$digest
运行它,获取当前值(watch.get(scope)
),并将其与watch.last
进行比较。如果当前值不等于watch.last
(始终用于第一次比较)$digest
将dirty
设置为true
。处理所有作用域时,如果dirty==true
$digest
从$rootScope
开始另一次深度优先遍历<代码>$digest在dirty==false或遍历次数==10时结束。在后一种情况下,将记录错误“10$digest()iterations reacted.”
现在关于ngRepeat
。对于每个watch.get
调用,它存储来自集合的对象(返回getEntities
)以及缓存中的附加信息(通过hashKey
)。对于每个watch.get
callngRepeat
尝试通过其hashKey
从缓存中获取对象。若它不存在于缓存中,ngRepeat
将其存储在缓存中,创建新的作用域,将对象放在其上,创建DOM元素
现在开始。通常,hashKey
是由生成的唯一数字。但也有可能<代码>哈希键在生成后存储在对象中,以备将来使用
示例生成错误的原因:函数getEntities()
始终返回带有新对象的数组。此对象没有hashKey
,并且不存在于ngRepeat
缓存中。因此,ngRepeat
对每个watch.get
使用{{entity.id}
的新watch为其生成新的作用域。第一次watch.get
上的此手表具有watch.last==initWatchVal
。所以watch.get()!=观察。最后一次
。因此,$digest
开始新的遍历。因此,ngRepeat
使用新手表创建新范围。所以经过10次遍历后,您将得到错误
如何修复它
getEntities()
时创建新对象hashKey
方法。有关示例,请参见希望了解AngularJS内部结构的人能够纠正我在某些方面的错误。在repeat之外初始化数组
<body ng-app>
<div ng-init="entities = getEntities()">
<div ng-repeat="entity in entities">
Hello {{entity.id}}!
</div>
</div>
</body>
你好{{entity.id}!
基于@przno注释
<body ng-app>
<div ng-repeat="item in t = angular.equals(t, getEntities()) ? t : getEntities()">
Hello {{item.id}}!
</div>
</body>
你好{{item.id}}!
顺便说一句,Artem Andreev提出的第二个解决方案不适用于Angular 1.1.4及更高版本,而第一个解决方案不能解决问题。因此,我现在恐怕这是一个功能上没有缺点的不那么尖锐的解决方案+1谢谢你。我有同样的问题,不能使用静态属性$$hashKey应该记录在手册IMO的ngRepeat页面上。你知道从1.1.3到1.1.4的变化影响了这一点吗?在1.1.4之前,这实际上是有效的。变更日志中没有关于它的任何内容,我无法解释出区别是什么。当前的行为是有道理的。另外,如果可以,请检查一下:我不确定我的答案是否正确。因此,按照
的建议,不要在每个getEntities()上创建新对象调用。
它可以很容易地修复,如下所示:
如果数组发生变化,getEntities()
始终返回相同的数组,则我前面的注释中的解决方案会起作用,在ng repeat
中,如果函数的参数在每次迭代中都发生更改,则使用属性可能是唯一的方法。如果getEntities()
在程序的生命周期中返回不同的内容,则这不起作用。例如,假设getEntities()
触发$http.get
。当get finally resolve(您进行了AJAX调用)时,实体
将已经初始化。从angular docs中,ngInit的唯一适当用途是对ngRepeat的特殊属性进行别名。除此之外,您应该使用控制器而不是ngInit来初始化作用域上的值。
我认为主要的一点是通过任何方式“在repeat之外初始化数组”。。。还有@Nighto good call on promises你是说item.id吗?如果entity.id是您的意思,您能解释一下吗
<body ng-app>
<div ng-repeat="item in t = angular.equals(t, getEntities()) ? t : getEntities()">
Hello {{item.id}}!
</div>
</body>