为什么将 toArray 过滤器与 ng-repeat 和字符串对象一起使用会导致无限摘要循环?
Why using toArray filter with ng-repeat and an object of strings causes an infinite digest loop?
我想在遍历对象属性时将 orderBy 过滤器与 ng-repeat 指令一起使用。
由于 orderBy 过滤器仅适用于数组,Angular doc 建议使用 toArray 过滤器。
toArray 过滤器的工作原理非常棒,对象属性如下:
var obj = {
a: { name: 'A' },
b: { name: 'B' },
c: { name: 'C' }
};
但是当与非对象属性一起使用时,它会导致无限摘要循环:
var obj = {
a: 'A',
b: 'B',
c: 'C'
};
这里 plunker 说明了这个问题。
无论如何你不应该那样做,过滤器在转换数据时通常不是个好主意,因为每次摘要循环进行循环时它都会被重新计算。你的 plunker 不起作用,所以很难说为什么,但看代码我会说它确实在每个摘要循环中创建了全新的数组,并且在对象的情况下它添加了 $key 属性,这有助于停止摘要循环。它不能将这样的 属性 添加到字符串中。但我不太确定。
编辑:
当您将 console.log 添加到 toArray:
return Object.keys(obj).map(function (key) {
var value = obj[key];
console.log(key, value);
return angular.isObject(value) ?
Object.defineProperty(value, '$key', { enumerable: false, value: key}) :
{ $key: key, $value: value };
});
在日志中您可以看到问题的答案:
VM596 angular-toArrayFilter.js:15 b b
VM596 angular-toArrayFilter.js:15 a a
VM596 angular-toArrayFilter.js:15 c Object {p: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a"}
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $key: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $key: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $key: "a"}
VM596 angular-toArrayFilter.js:15 c c
VM596 angular-toArrayFilter.js:15 b b
VM596 angular-toArrayFilter.js:15 a a
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $$hashKey: "object:11", $key: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $$hashKey: "object:10", $key: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $$hashKey: "object:9", $key: "a"}
在 case objects 中,angular 使用相同的对象并且不会创建新的对象。这样它就可以假设数组没有改变并结束摘要循环。对于字符串值,它会在每次过滤器为 运行 时创建新对象,因此它假定每次都创建不同的数组,因此它无法结束摘要循环。
我想在遍历对象属性时将 orderBy 过滤器与 ng-repeat 指令一起使用。 由于 orderBy 过滤器仅适用于数组,Angular doc 建议使用 toArray 过滤器。
toArray 过滤器的工作原理非常棒,对象属性如下:
var obj = {
a: { name: 'A' },
b: { name: 'B' },
c: { name: 'C' }
};
但是当与非对象属性一起使用时,它会导致无限摘要循环:
var obj = {
a: 'A',
b: 'B',
c: 'C'
};
这里 plunker 说明了这个问题。
无论如何你不应该那样做,过滤器在转换数据时通常不是个好主意,因为每次摘要循环进行循环时它都会被重新计算。你的 plunker 不起作用,所以很难说为什么,但看代码我会说它确实在每个摘要循环中创建了全新的数组,并且在对象的情况下它添加了 $key 属性,这有助于停止摘要循环。它不能将这样的 属性 添加到字符串中。但我不太确定。
编辑: 当您将 console.log 添加到 toArray:
return Object.keys(obj).map(function (key) {
var value = obj[key];
console.log(key, value);
return angular.isObject(value) ?
Object.defineProperty(value, '$key', { enumerable: false, value: key}) :
{ $key: key, $value: value };
});
在日志中您可以看到问题的答案:
VM596 angular-toArrayFilter.js:15 b b
VM596 angular-toArrayFilter.js:15 a a
VM596 angular-toArrayFilter.js:15 c Object {p: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a"}
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $key: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $key: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $key: "a"}
VM596 angular-toArrayFilter.js:15 c c
VM596 angular-toArrayFilter.js:15 b b
VM596 angular-toArrayFilter.js:15 a a
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $$hashKey: "object:11", $key: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $$hashKey: "object:10", $key: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $$hashKey: "object:9", $key: "a"}
在 case objects 中,angular 使用相同的对象并且不会创建新的对象。这样它就可以假设数组没有改变并结束摘要循环。对于字符串值,它会在每次过滤器为 运行 时创建新对象,因此它假定每次都创建不同的数组,因此它无法结束摘要循环。