9

我一直在考虑尝试编写过滤器,但它非常令人沮丧。

这是我为编写“块”过滤器而关注的一些资源

https://groups.google.com/forum/#!topic/angular/IEIQok-YkpU https://groups.google.com/forum/#!topic/angular/gEv1-YV-Ojg

我试了一下,取得了一些成功。但发现版本之间的行为存在差异

所描述的生成 $$hashKey 的方法在 1.1.5 版本中不起作用。第一个小提琴很好,而第二个产生迭代错误,即使代码完全相同:

http://jsfiddle.net/nRGTX/38/ - 1.0.3 版本

http://jsfiddle.net/nRGTX/39/ - 1.1.5 版本

 Error: 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: $watchCollectionWatch; newVal: 16; oldVal: 14"],["fn: $watchCollectionWatch; newVal: 18; oldVal: 16"],["fn: $watchCollectionWatch; newVal: 20; oldVal: 18"],["fn: $watchCollectionWatch; newVal: 22; oldVal: 20"],["fn: $watchCollectionWatch; newVal: 24; oldVal: 22"]]

有什么解决方法/正确的方法来写这个吗?

4

1 回答 1

12

从版本 1.1.4 开始,该ng-repeat指令对您正在迭代的集合有一个监视,以确保它没有更改。它的工作方式是比较数组中的每个项目,如果项目不相等(在===某种意义上),它认为集合已更新。至少这是我查看代码后的理解。

如果您在典型意义上使用过滤器,您只返回原始项目的子集,那么每次返回的项目都是相同的。但是,由于您正在构建一个全新的结构,因此数组中的项目每次都不同(即使它们的内容相同),所以手表认为集合在不断变化。

我能想出的唯一解决方案是创建先前返回结果的缓存。每次调用块过滤器时,它都会检查您之前是否执行过具有相同数组和块大小的过滤器。如果是,则返回缓存的结果。

为此,您应该更新您的过滤器函数,使其看起来像这样:

return function(array, chunkSize) {
  if (!(array instanceof Array)) return array;
  if (!chunkSize) return array;

  // Create empty cache if it doesn't already exist.  
  if (typeof myApp.chunkCache === "undefined") {
    myApp.chunkCache = [];
  }

  // Search the cache to see if we filtered the given array before.
  for (var i = 0; i < myApp.chunkCache.length; i++) {
    var cache = myApp.chunkCache[i];
    if (cache.array == array && cache.chunkSize == chunkSize) {
      return cache.result;
    }
  }

  // If not, construct the chunked result.
  var result = chunkArray(array, chunkSize);
  defineHashKeys(result);

  // And then add that result to the cache.
  var cache = {
    array: array,
    chunkSize: chunkSize,
    result: result
  };
  myApp.chunkCache.push(cache);

  return result;
}

我还应该指出,您可能可以删除该defineHashKeys调用,因为我认为它在此代码中没有任何用途。我只留下它,因为它在您的原始代码中。当我删除它时,它似乎没有任何区别。

于 2013-07-15T16:48:41.227 回答