jtf*_*ank 8 angularjs angularjs-ng-repeat angularjs-filter
我正在尝试将转换应用于我的过滤器中的对象,这会导致返回一个新对象数组.这是因为我想在应用变换后过滤对象并显示变换的结果.但是,我最终得到了一个无限的摘要,因为我显示的对象与我输入的对象不同(比较它们时$$ids).我想解决这个问题如下:
使用跟踪表达式track by item.id,并将原始对象分配ids给每个转换的对象.虽然我的所有对象目前都有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);
}
}]
);
Run Code Online (Sandbox Code Playgroud)
以下是我尝试使用它的方法:
<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>
Run Code Online (Sandbox Code Playgroud)
哦,理想情况下ngClick返回原始对象,但我总是可以用它包围一个函数来查看它.
这个问题的一个解决方案是你有一个幂等函数,因为对象ID认为Angular不是幂等的(因此导致你记下的$ digest循环问题)是使用lo-dash/underscore _.memoize来缓存你的函数的结果.
这将保证对于任何给定的缓存键,您的过滤器将始终返回完全相同的对象(包括$$id).这样你就不必玩游戏了$$id,你可以获得不必在每个$ digest循环上重新计算过滤结果的性能优势.
以下是缓存过滤器结果的方法:
return _.memoize(function(objects, transformer, expression) { ... },
function(objects,transformer,expression){
return objects +transformer.name + expression;
});
Run Code Online (Sandbox Code Playgroud)
对于您的情况,一个重要的注意事项是默认情况下_.memoize使用第一个函数参数(objects在本例中)作为缓存键.由于您的过滤器可能会产生给予不同变压器功能和表达不同的结果,我已经添加了可选的第二个参数-使用散列函数objects,expression和名transformer函数产生一个缓存键.
以下是使用此代码的简化版本: 小提琴
Angular 用于angular.equals检测范围变化。跟踪表达式用于将数组项与 DOM 元素进行匹配,这样当您过滤或重新排序数组时,Angular 只会显示、隐藏或重新排序某些元素,而不是重建整个子树。
看看这个简单的例子: http: //jsfiddle.net/Nb8mX/
function Ctrl($scope) {
$scope.transform = function(item) {
item.abc *= 2;
return true;
};
$scope.data = [
{abc: 123, def: 1},
{abc: 456, def: 2},
{abc: 789, def: 3}
];
}
Run Code Online (Sandbox Code Playgroud)
通过过滤器修改项目会导致无限摘要循环track by,而不管 ,而在内部执行相同的ng-init操作不会出现问题:
<ul ng-app="blah" ng-controller="Ctrl">
<li ng-repeat="item in data | filter : transform">{{ item.abc }}</li>
<li ng-repeat="item in data | filter : transform track by item.def">{{ item.abc }}</li>
<li ng-repeat="item in data" ng-init="transform(item)">{{ item.abc }}</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
这表明您可以编写指令而不是过滤器。
如果有人知道更好的解决方案,我也很乐意学习。
| 归档时间: |
|
| 查看次数: |
2756 次 |
| 最近记录: |