显然我还没有理解ng-repeat
、$$hashKeys
和track by
背后的机制。
我目前在我的项目中使用的是AngularJS 1.6。
问题:
我有一个复杂对象的数组,我想在我的视图中使用它来渲染一个列表。但为了得到所需的结果,我需要先修改(或映射/增强/更改)这些对象:
const sourceArray = [{id: 1, name: 'Dave'}, {id:2, name: Steve}]
const persons = sourceArray.map((e) => ({enhancedName: e.name + e.id}))
//Thus the content of persons is:
//[{enhancedName: 'Dave_1'}, {enhancedName: 'Steve_2'}]
绑定此内容到视图应该像这样工作:
<div ng-repeat="person in ctrl.getPersons()">
{{person.enhancedName}}
</div>
然而,这显然会遇到一个$digest()
循环,因为.map
每次调用时都会返回新的对象实例。由于我将其绑定到ng-repeat通过一个函数中,它会在每个$digest
中重新评估,模型无法稳定下来,Angular会持续重新运行$digest
周期,因为这些对象被标记为$dirty
。
我为什么感到困惑
现在这不是一个新问题,已经有几种解决方案:
在2012年的一个Angular问题中,Igor Minar本人建议手动设置$$hashKey属性以告诉angular生成的对象是相同的。这是他的工作范例,但由于即使在非常简单的示例中在我的项目中使用它时仍然遇到了$digest
循环,因此我尝试升级fiddle中的Angular版本。出于某种原因,它崩溃了。
好吧...自Angular 1.3以来,我们有了track by
,它应该解决这个精确问题。不过,两者都
<div ng-repeat="person in ctrl.getPersons() track by $index">
并且
<div ng-repeat="person in ctrl.getPersons() track by person.enhancedName">
与$digest
循环崩溃。我原以为track by
语句应该让angular相信它正在处理相同的对象,但显然不是这种情况,因为它仍在检查它们是否有变化。老实说,我不知道如何正确调试此问题。
问题:
是否可以使用过滤/修改后的数组作为ng-repeat的数据源?
我不想将修改后的数组存储在我的控制器上,因为我需要不断更新其数据,然后就必须手动维护和刷新它,而不能依赖于数据绑定。
sourceArray
比此示例复杂得多。因此,我想从中删除所有不需要的数据以使其更易读。除此之外,我还需要将一些信息和业务逻辑映射到其他数据类型(例如,“当此数组具有10个或更多条目时,此切换按钮应呈现为“已单击”)。为了正确地将其与ng-model绑定,我想使用带有自定义getter和setter方法的Object.defineProperty
,其中包含相应的业务逻辑。 - H W