自定义过滤器使用 angular-meteor 生成无限摘要循环
Custom filters produces infinit digest loop with angular-meteor
我遇到了问题,自定义过滤器在 angular-meteor 中产生无限摘要循环。 (Angular error description page)
我在这个 plunk 中用纯 angular 做了一个工作示例。当我尝试使用 es6 风格的 angular-meteor 时,脚本在无限循环中是 运行。
这是我的控制器
class MyController {
constructor($scope, $reactive) {
'ngInject';
$reactive(this).attach($scope);
this.items = [{ item: 'item1' }, { item: 'item2' }, { item: 'item3' }, { item: 'item4' }];
}
}
这是模板
<div ng-repeat="item in vm.items | testFilter">
Item: {{item.item}}
</div>
过滤器实现只是复制原始内容(因此它不过滤任何内容,但可以用于演示)。
[...]
.filter('testFilter', () => {
return (items) => {
var result = angular.copy(items);
// maybe splice some elements from result
return result;
};
})
[...]
我不明白为什么这在普通 angularjs 中有效但在 meteor 中无效。是因为 es6=>es5 翻译吗?我是否遗漏了什么并且以错误的方式使用过滤器?还是我发现了 angular-meteor 错误?
我很乐意提供一些建议。 :)
更新
- 我发现,只有链中的最后一个过滤器会产生此错误。所以当变量被传递到范围时,它可能会发生。
- 当我在构建目录中检查结果时,ES6=>ES5 翻译对我来说似乎没问题。
我为这个问题创建了一个通用的解决方法,因此在将现有的 angular 应用程序迁移到 meteor 时,自定义过滤器的逻辑在许多情况下可以保持不变。 (Gist with comments)
.filter('fixLoopFilter', () => {
const instanceCache = {};
return (items) => {
const hash = CryptoJS.SHA1(angular.toJson(items)).toString();
if (!instanceCache[hash]) instanceCache[hash] = [];
instanceCache[hash].length = 0;
items.map((item) => {
instanceCache[hash].push(item);
});
return instanceCache[hash];
};
})
它并没有真正过滤输入数组的任何元素,而是 returns 输入的克隆。克隆是每个输入配置的相同实例。这不是深度克隆。如果输入数组包含对象,结果数组将包含相同的实例。
用法:
- 将此过滤器添加到项目的基础模块中。
在您的模板中将其用作链中应用的 last 过滤器:
ng-repeat="vm.items | customFilter | fixLoopFilter"
缺点:
对于大型输入数组或大型对象数组,此过滤器可能会消耗性能和内存。它只是作为一种解决方法,直到问题得到解决或有更好的解决方法。
我遇到了问题,自定义过滤器在 angular-meteor 中产生无限摘要循环。 (Angular error description page)
我在这个 plunk 中用纯 angular 做了一个工作示例。当我尝试使用 es6 风格的 angular-meteor 时,脚本在无限循环中是 运行。
这是我的控制器
class MyController {
constructor($scope, $reactive) {
'ngInject';
$reactive(this).attach($scope);
this.items = [{ item: 'item1' }, { item: 'item2' }, { item: 'item3' }, { item: 'item4' }];
}
}
这是模板
<div ng-repeat="item in vm.items | testFilter">
Item: {{item.item}}
</div>
过滤器实现只是复制原始内容(因此它不过滤任何内容,但可以用于演示)。
[...]
.filter('testFilter', () => {
return (items) => {
var result = angular.copy(items);
// maybe splice some elements from result
return result;
};
})
[...]
我不明白为什么这在普通 angularjs 中有效但在 meteor 中无效。是因为 es6=>es5 翻译吗?我是否遗漏了什么并且以错误的方式使用过滤器?还是我发现了 angular-meteor 错误?
我很乐意提供一些建议。 :)
更新
- 我发现,只有链中的最后一个过滤器会产生此错误。所以当变量被传递到范围时,它可能会发生。
- 当我在构建目录中检查结果时,ES6=>ES5 翻译对我来说似乎没问题。
我为这个问题创建了一个通用的解决方法,因此在将现有的 angular 应用程序迁移到 meteor 时,自定义过滤器的逻辑在许多情况下可以保持不变。 (Gist with comments)
.filter('fixLoopFilter', () => {
const instanceCache = {};
return (items) => {
const hash = CryptoJS.SHA1(angular.toJson(items)).toString();
if (!instanceCache[hash]) instanceCache[hash] = [];
instanceCache[hash].length = 0;
items.map((item) => {
instanceCache[hash].push(item);
});
return instanceCache[hash];
};
})
它并没有真正过滤输入数组的任何元素,而是 returns 输入的克隆。克隆是每个输入配置的相同实例。这不是深度克隆。如果输入数组包含对象,结果数组将包含相同的实例。
用法:
- 将此过滤器添加到项目的基础模块中。
在您的模板中将其用作链中应用的 last 过滤器:
ng-repeat="vm.items | customFilter | fixLoopFilter"
缺点:
对于大型输入数组或大型对象数组,此过滤器可能会消耗性能和内存。它只是作为一种解决方法,直到问题得到解决或有更好的解决方法。