gpt4 book ai didi

javascript - ng-repeat 中的函数导致无限 $digest-loop

转载 作者:可可西里 更新时间:2023-11-01 02:12:10 24 4
gpt4 key购买 nike

显然我还不了解ng-repeat$$hashKeystrack by 背后的机制。

我目前在我的项目中使用 AngularJS 1.6。

问题:

我得到了一组复杂的对象,我想用它来在我的 View 中呈现一个列表。但要获得所需的结果,我需要先修改(或映射/增强/更改)这些对象:

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'}]

将它绑定(bind)到 View 应该像这样工作:

<div ng-repeat="person in ctrl.getPersons()">
{{person.enhancedName}}
</div>

然而,这显然会遇到 $digest() 循环,因为 .map 每次被调用时都会返回新的对象实例。因为我通过一个函数将它绑定(bind)到 ng-repeat,它在每个 $digest 中都会被重新评估,模型不稳定并且 Angular 不断重新运行 $digest-cycles 因为这些对象被标记为 $dirty

为什么我很困惑

现在这不是一个新问题,有几种解决方案:

an Angular-Issue from 2012 Igor Minar 自己建议手动设置 $$hashKey-Property 来告诉 Angular 生成的对象是相同的。 This是他的工作 fiddle ,但由于即使是这个非常微不足道的例子,当我在我的项目中使用它时仍然会遇到 $digest 循环,我尝试在 fiddle 中升级 Angular-Version。由于某种原因it crashes .

好的...从 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 的数据源?

我不想将修改后的数组存储在我的 Controller 上,因为我需要不断更新它的数据,然后必须在 Controller 中手动维护和刷新它,而不是依赖数据绑定(bind)。

最佳答案

您提供的“it crashes” fiddle 并没有为我生成无限摘要。事实上:它甚至没有成功地引导 Angular 应用程序(看起来引导不能在最新的 Angular 中以这种方式完成)。

rewrote it使用我理解的 Angular 引导机制。它重现了崩溃,就像你说的那样。

我找到了成功的方法track by stringified JSON .

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>

<script>
angular.module('myApp',[])
.controller('Ctrl', ['$scope', function($scope) {
angular.extend($scope, {
stringify: function(x) { return JSON.stringify(x) },
getList: function() {
return [
{name:'John', age:25},
{name:'Mary', age:28}
];
}
});
}]);
</script>

<div ng-app="myApp">

<div ng-controller="Ctrl">
I have {{getList().length}} friends. They are:
<ul>
<li ng-repeat="friend in getList() track by stringify(friend)">
[{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
</li>
</ul>
</div>

</div>

即我们提供了一个跟踪函数,stringify()。也可能有一个内置的 Angular。

track by $index 也同样有效——与您的发现相反。我认为 JsFiddle 稍微破坏了实验*

*以下是轶事。我相信我在 JsFiddle 本身 方面遇到了一些问题。例如:我的 track by stringify() 示例在我 fork Fiddle 并在新的浏览上下文中再次尝试相同的代码之前不起作用。我相信一旦我得到任何无限摘要:JsFiddle 总是无限摘要。似乎有一些从以前的运行中挥之不去的状态。所以,我建议你在 JsFiddle 中看到的任何失败,你在一个新的 JsFiddle 中重试

至于为什么您的 $$hashKey 技巧会导致无限摘要 — 我认为 Angular 不期望 $$hashKey 是一个函数。因此,它可能没有调用您的函数,而是对分配给 $$hashKey 的函数进行了引用比较

由于每次调用 getList() 时,您都将比较器的 新实例 分配给了 $$hashKey:引用可以永远在随后的摘要中是相等的,所以它会一直尝试摘要。

编辑:更新了 StackOverflow 嵌入和 JsFiddle 以使用 HTTPS CDN(以避免与混合内容安全性冲突)。

关于javascript - ng-repeat 中的函数导致无限 $digest-loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46421829/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com