3

我想使用 AngularJS 来显示一个随机列表 - 但只有前几个元素。目前,我在 HTML 模板中执行了改组和限制,如下所示

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

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

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

显而易见的解决方案是在控制器中的列表显示之前对其进行洗牌 - 但我确实希望每次用户更新视图时显示的元素选择都会发生变化。

编辑:这是我正在尝试实现的一个更好的示例- 该应用程序现在允许您在两个列表之间切换,每次都会被打乱和限制。

4

3 回答 3

2

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

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;
    };
});

无论如何,修改过滤器范围内的数据并不是一个好习惯。如果您需要共享这个打乱的数组 - 在您的控制器/服务/....中打乱它。因此,var o = arr.slice(0, length)复制该数组,因此我们保持原始数组不变。

于 2013-02-11T08:30:06.757 回答
1

这个小提琴演示了“控制器中的过滤器”方法。改组不是实际创建过滤器,而是定义为常规函数并应用于$scope.array.

于 2013-02-11T20:01:20.900 回答
0

我认为 tgat 问题是您的过滤器修改了源数组。即使您返回新数组,这也将是一个简单的问题。它是如何进行脏检查的:它不断评估表达式,直到它“稳定”(或 10 次迭代)。这篇文章中有更多描述:https ://groups.google.com/forum/m/#!msg/angular/IEIQok-YkpU/InEXv61MrkMJ

解决方案是控制器中的预洗牌值,因此表达式将在每个脏检查阶段返回相同的值......对不起,但这是目前最好的方法(除非你想用 $$hash 玩脏游戏让 ngRepeat 忘记那个yourexpression 计算为相同的值:))

于 2013-02-11T07:44:18.280 回答