我希望实现以下目标:
- 能够以随机顺序显示数组中的图像。
为了解决这个问题,我决定创建一个过滤器:
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>
但是,我收到此错误:
Uncaught Error: [NG-Modular Error] [$rootScope:infdig] 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: [[{"msg":"fn: expressionInputsWatch","newVal":"http://localhost:3002/documents/view/158","oldVal":"http://localhost:3002/documents/view/159"},{"msg":"fn:
经过一些研究,我发现这与值(value)观的变化有关,但我正在改变我的值(value)观。
现在我可以理解范围可能正在发生变化。然而,我注意到,即使我有一个像这样的简单过滤器:{{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);
};
那么解决办法是什么?
最佳答案
要修复无限摘要,您需要将过滤器包装在 memoize
函数中。解决问题的最佳方法是从 npm
安装 knuth-shuffle
和 lodash
,然后使用您喜欢的任何模块系统来创建过滤器。此示例使用 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();
};
关于javascript - 如何创建没有无限摘要循环的随机/随机过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30435382/