AngularJS shuffle和limitTo列表

时间:2013-02-11 00:54:06

标签: angularjs

我想使用AngularJS来显示一个混洗列表 - 但只显示前几个元素。目前,我在HTML模板中执行了混洗和限制,在this fiddle中进行了演示:

<li ng-repeat="value in array | shuffle | limitTo:1">
    {{value}}
</li>

这样可以正常工作,但是当列表中的项目多于显示的项目时,会导致Angular超过10 $digest次迭代,如示例所示。据我所知,正在发生的事情是,某些东西正在观察列表的过滤和限制值,当所有元素都不会一直显示时,很可能会发生变化。

如何在不破坏Angular的情况下实现此效果?当然,它仍然可以正常工作,但效率低下,可能表明我所做的不正确,应该以其他方式实现。

显而易见的解决方案是在控制器显示之前对控制器中的列表进行随机播放 - 但我确实希望每次用户更新视图时显示的元素选择都会更改。

编辑:这是我想要实现的better example - 应用程序现在允许您在两个列表之间切换,每次都会进行洗牌和限制。

3 个答案:

答案 0 :(得分:1)

如前所述 - 角度等待表达式变得稳定。 因此,最好的方法是在将数组传递给视图之前对其进行洗牌。 无论如何,有一些技巧可以帮助你保持清洁。

http://jsfiddle.net/zc3YH/3/

在这个小提琴中,我们缓存shuffle结果,而长度保持不变。因此,当阵列发生变化时,不会重新调整阵列,但是当长度发生变化时。您可以实现更复杂的缓存行为。因此,主要思想是仅对同一个数组进行一次洗牌,并仅在数组更新时重新洗牌。

当前的过滤器实现非常糟糕,因为它只缓存单个数组,因此如果您将使用此过滤器两​​次 - 它将被破坏。因此,缓存应该使用像hashKey这样的数组来完成,以使不同的数组不同。

shufflemodule.filter('shuffle', function() {
    var shuffledArr = [],
        shuffledLength = 0;
    return function(arr) {
        var o = arr.slice(0, arr.length);
        if (shuffledLength == arr.length) return shuffledArr;
        for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
        shuffledArr = o;
        shuffledLength = o.length;
        return o;
    };
});

无论如何,在过滤器中修改范围内的数据不是一个好习惯。如果你需要共享这个混洗数组 - 在你的控制器/ service /中随机播放....所以,var o = arr.slice(0, length)复制那个数组,因此我们保持原始数组不被修改。

答案 1 :(得分:1)

This fiddle演示了“控制器中的过滤器”方法。实际上,shuffling不是实际创建过滤器,而是定义为常规函数并应用于$scope.array

答案 2 :(得分:0)

我认为tgat问题是你的过滤器修改了源数组。即使你返回新阵列,也会出现问题。它的检查工作原理如何:它一直在评估表达式,直到它“稳定”(或10次迭代)。这篇文章中描述了更多内容:https://groups.google.com/forum/m/#!msg/angular/IEIQok-YkpU/InEXv61MrkMJ

解决方案将是控制器中的预先洗牌值,因此表达式将返回每个脏检查阶段相同的值...对不起,但这是现在最好的方法(除非你想玩带有$$哈希的脏游戏让ngRepeat beleave berexpression评估为相同的值:))