H W*_*H W 12 javascript angularjs angularjs-ng-repeat
显然我还没有理解背后的机制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'}]
Run Code Online (Sandbox Code Playgroud)
将此绑定到视图应该像这样工作:
<div ng-repeat="person in ctrl.getPersons()">
{{person.enhancedName}}
</div>
Run Code Online (Sandbox Code Playgroud)
然而,这显然会进入$digest()-loop,因为.map每次调用它都会返回新的对象实例.由于我通过函数将其绑定到ng-repeat,因此它会在每个函数中重新评估$digest,模型不会稳定,Angular会保持重新$digest循环 - 因为这些对象被标记为$dirty.
为什么我很困惑
现在这不是一个新问题,有几个解决方案:
在2012年的Angular-Issue中, Igor Minar自己建议手动设置$$ hashKey-Property以告知angular生成的对象是相同的.这是他的工作小提琴,但是因为即使这个非常简单的例子$digest在我的项目中使用它时仍然遇到了-loop,我尝试在小提琴中升级Angular-Version.由于某种原因它崩溃了.
好的......从Angular 1.3开始,我们track by应该从根本上解决这个问题.但两者都有
<div ng-repeat="person in ctrl.getPersons() track by $index">
Run Code Online (Sandbox Code Playgroud)
和
<div ng-repeat="person in ctrl.getPersons() track by person.enhancedName">
Run Code Online (Sandbox Code Playgroud)
用$digest-loop 崩溃.我的印象是track by声明应该让角度相信它适用于相同的对象,但显然情况并非如此,因为它只是不断检查它们的变化.说实话,我不知道如何正确调试原因.
题:
是否可以使用过滤/修改的数组作为ng-repeat的数据源?
我不想将修改后的数组存储在我的控制器上,因为我需要不断更新其数据,然后必须在控制器中手动维护和刷新它,而不是依赖于数据绑定.
你提供的“它崩溃了”小提琴并没有为我产生无限的摘要。事实上:它甚至没有成功引导 Angular 应用程序(看起来在最新的 Angular 中无法以这种方式引导)。
\n\n我重写了它以使用我理解的 Angular 引导机制。正如你所说,它重现了崩溃。
\n\n我找到了一种通过字符串化 JSON成功跟踪它的方法。
\n\n<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>\r\n\r\n<script>\r\nangular.module(\'myApp\',[])\r\n.controller(\'Ctrl\', [\'$scope\', function($scope) {\r\n angular.extend($scope, {\r\n stringify: function(x) { return JSON.stringify(x) },\r\n getList: function() {\r\n return [\r\n {name:\'John\', age:25},\r\n {name:\'Mary\', age:28}\r\n ];\r\n }\r\n });\r\n}]);\r\n</script>\r\n\r\n<div ng-app="myApp">\r\n\r\n<div ng-controller="Ctrl">\r\n I have {{getList().length}} friends. They are:\r\n <ul>\r\n <li ng-repeat="friend in getList() track by stringify(friend)">\r\n [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\r\n </li>\r\n </ul>\r\n</div>\r\n\r\n</div>Run Code Online (Sandbox Code Playgroud)\r\n即我们提供跟踪功能stringify()。可能也有一个 Angular 内置函数可以实现这一点。
track by $index与您的发现相反,\xe2\x80\x94 也有效。我认为 JsFiddle 稍微破坏了实验*
*以下内容为轶事。我相信我在JsFiddle 本身上遇到了一些问题。例如:我的track by stringify()示例不起作用,直到我分叉 Fiddle 并在新的浏览上下文中再次尝试相同的代码。我相信,一旦我得到任何无限摘要:JsFiddle 总是无限摘要。似乎之前的跑步中还残留着一些庄严的感觉。所以,我建议您在 JsFiddle 中看到的任何失败,您在新的 JsFiddle 中重试。
至于为什么你的$$hashKey技巧会导致无限摘要 \xe2\x80\x94 我认为 Angular 不希望$$hashKey成为一个函数。因此,它可能不是调用您的函数,而是对分配给 的函数进行了引用比较$$hashKey。
由于每次调用时都分配给比较器的新实例$$hashKey:后续摘要中的引用永远不会相等,因此它将永远继续尝试摘要。getList()
编辑:更新了 StackOverflow 嵌入和 JsFiddle 以使用 HTTPS CDN(以避免与混合内容安全性发生冲突)。
\n| 归档时间: |
|
| 查看次数: |
597 次 |
| 最近记录: |