我正在尝试将转换应用于我的过滤器中的对象,这会导致返回一个新对象数组.这是因为我想在应用变换后过滤对象并显示变换的结果.但是,我最终得到了一个无限的摘要,因为我显示的对象与我输入的对象不同(比较它们的$$ids).我想解决这个问题如下:
>使用跟踪表达式(如track by item.id)并将原始对象的ID分配给每个已转换的对象.虽然我的所有对象当前都有id,但这似乎是一个坏主意,因为它使得过滤器不那么通用 – 原始对象必须具有id,转换不能设置id(因为它将被覆盖)等.
>将原始对象的$$id分配给已转换的对象.基于我的理解,这似乎是hackish,$$id应该是只读的.
>根据转换过滤的结果返回原始对象的子集.这可能会导致性能问题,因为需要在过滤器和显示表达式中应用转换,并且我必须循环回转换/过滤的项目以选择要返回的正确原始项目.
这是过滤器:
listModule.filter('ui.filter.transformFilter',['$filter','$id',function($filter,$id) { var Filter = $filter('filter'); return function(objects,transformer,expression) { // precondition- we need a list of objects if (!_.isArray(objects)) { return objects; } var transformed = []; for (var i = 0; i < objects.length; i++) { transformed[i] = transformer(objects[i]); } return filtered = Filter(transformed,expression); } }] );
以下是我尝试使用它的方法:
<tr ng-repeat="item in list.items | ui.filter.transformFilter:list.transformerFunction:list.search" ng-click="list.select({'item': item})" class="list-item"> <td ng-repeat="label in list.labels" ng-bind-html="item[label.key]"></td> </tr>
哦,理想情况下,ngClick返回原始对象,但我总是可以在它周围包装一个函数来查看它.
这个问题的一个解决方案是你有一个幂等函数,Angular,由于对象ID,认为不是幂等的(因此导致你记下的$digest循环问题)是使用lo-dash / underscore的
_.memoize
来缓存你的函数的结果.
这将保证对于任何给定的缓存键,您的过滤器将始终返回完全相同的对象(包括$$id).这样您就不必使用$$id玩游戏,并且您可以获得不必在每个$digest循环上重新计算过滤结果的性能优势.
以下是缓存过滤器结果的方法:
return _.memoize(function(objects,expression) { ... },function(objects,expression){ return objects +transformer.name + expression; });
对于您的情况,一个重要的注意事项是,默认情况下_.memoize使用第一个函数参数(在本例中为对象)作为缓存键.由于您的过滤器在给定不同的变换器函数和表达式时可能会产生不同的结果,因此我添加了可选的第二个参数 – 一个使用对象,表达式和变换器函数名称的哈希函数来生成缓存键.