我想要实现以下目标:
为了解决这个问题,我决定创建一个过滤器:
var app = angular.module('app');
app. filter('randomizer', randomizer);
function randomizer() {
return function (collection, defaultValue) {
var result = defaultValue;
if (!!collection) {
if (Array.isArray(collection) && collection.length === 1) {
result = collection[0] || defaultValue;
} else if (!Array.isArray(collection)) {
result = collection || defaultValue;
} else {
// randomize here please
var idx = parseInt(((Math.random()) * collection.length));
result = collection[idx] || defaultValue;
}
}
return result;
}
}
现在在模板中,我打电话给:
<div class="masonry-pin masonry-brick" ng-repeat="p in vm.list | orderBy: 'updatedAt':true">
<img ng-src="{{vm.baseUrl + 'documents/view/' + ( p.documents | randomizer:{id: 'notfound'}:p.id).id }}">
</div>
但是,我收到此错误:
未捕获错误:[NG-Modular Error] [$ rootScope:infdig] 10 $ digest() 迭代达成。中止!观察者在最近5次迭代中被解雇: [[{ “msg” 中:“FN: expressionInputsWatch “ ”的newval“: ”http://localhost:3002/documents/view/158“, ”OLDVAL“: ”http://localhost:3002/documents/view/159“},{ ”msg“ 中:” FN:
在做了一些研究之后,我发现这与价值变化有关,但我改变了我的价值观。
现在我可以理解一些范围如何变化。但是,我注意到即使我有一个像这样的简单过滤器:{{p.documents |控制台}}
,控制台过滤器只需一个数组并在控制台中打印。
现在,当我在列表中有10个对象时,它正在调用过滤器30次。
这是控制台过滤器的方式,但对于10个项目,它调用了66次。
为什么??
app.filter('console', pipeConsole);
function pipeConsole() {
return function (value, o) {
print(value);
print(o);
print(count);
}
function print(o) {
if (!!o) {
console.log(o);
}
else if (o === null) {
console.warn(o);
}
}
};
在这里,我甚至没有回复不同的价值......(如果我按照这里解释的逻辑 - Angular: infinite digest loop in filter)
即使它不是过滤器,也会导致此问题
现在我已经创建了一个服务功能,我遇到了这个问题。
<img ng-src="{{vm.baseUrl + 'documents/view/' + vm.random( p.documents , {id: 'notfound'}).id }}">
vm.random = function (a, s) {
return utility.randomizer(a, s);
};
那么解决方案是什么?
答案 0 :(得分:1)
要修复无限摘要,您需要将过滤器包装在memoize
函数中。解决问题的最佳方法是从knuth-shuffle
安装lodash
和npm
,然后使用您喜欢的任何模块系统来创建过滤器。这个例子是使用CommonJS / browserify。
var memoize = require('lodash/function/memoize');
var shuffle = require('knuth-shuffle');
app.filter('shuffle', function() {
return memoize(shuffle);
});
以这种方式创建过滤器时,如果将空值传递给shuffle
函数,则可能会出现问题。在这种情况下,只需添加一个支票:
app.filter('shuffle', function() {
return memoize(function(input) {
if (input === undefined) { return; }
return shuffle.apply(null, arguments);
});
});
您可以从this answer了解有关无限摘要问题的更多信息。
要重新排列列表,可以将任意$ scope属性传递给过滤器,然后在需要重新随机播放时更改该属性。递增数字或使用Math.random()
是一种很好的方法。这是有效的,因为结果是根据传递的参数进行缓存的,因此传递一个无用的参数会产生新的结果。
myList | shuffle:whatever
$scope.whatever = 0;
$scope.reshuffle = function() {
++$scope.whatever;
// OR
$scope.whatever = Math.random();
};