为什么使用带有ng-repeat和字符串对象的toArray过滤器会导致无限的摘要循环?

时间:2016-05-31 18:09:24

标签: javascript angularjs angularjs-ng-repeat ng-repeat angular-filters

我想在迭代对象属性时使用带有ng-repeat指令的 orderBy 过滤器。 由于orderBy过滤器仅适用于Array,Angular doc建议使用 toArray 过滤器。

toArray过滤器的工作方式类似于具有以下对象属性的魅力:

var obj = {
  a: { name: 'A' },
  b: { name: 'B' },
  c: { name: 'C' }
};

但是当与非对象属性一起使用时,它会导致无限摘要循环

var obj = {
  a: 'A',
  b: 'B',
  c: 'C'
};

这是一个说明问题的plunker

1 个答案:

答案 0 :(得分:1)

你不应该这样做,过滤器在转换数据时通常是个坏主意,因为每次摘要周期循环时都会重新计算过滤器。你的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"}

如果是对象,则角度使用相同的对象而不创建新对象。这样它就可以假设数组没有改变并结束了摘要周期。在字符串值的情况下,它在每次运行过滤器时都会创建新对象,因此它假定每次创建不同的数组时,它都不能结束摘要循环。