【问题标题】:AngularJS improve filtering for nested arraysAngularJS 改进了对嵌套数组的过滤
【发布时间】:2015-01-21 20:12:55
【问题描述】:

首先,我有某种可行的解决方案,但我只是想问是否可以对其进行调整以获得更好的性能。所以,我的嵌套数组结构看起来像这样:

$scope.clients = [
{
    name: "Ivan Drew",
    age: 21,
    company: "HP",
    apps: [
        {
            appName: "Facebook",
            used: "Y",
            installedDate: "21/12/2014"
        },
        {
            appName: "Instagram",
            used: "N",
            installedDate: "14/12/2014"
        }
    ]
},
{
    name: "John Roberts",
    age: 35,
    apps: [
        {
            appName: "Messenger",
            used: "Y",
            installedDate: "01/01/2015"
        },
        {
            appName: "Facebook",
            used: "Y",
            installedDate: "09/11/2014"
        },
        {
            appName: "Instagram",
            used: "Y",
            installedDate: "20/10/2014"
        }
    ]
},
{
    name: "Richard James",
    age: 28,
    apps: [
        {
            appName: "Instagram",
            used: "N",
            installedDate: "15/11/2014"
        }
    ]
}
];

现在,我想过滤此列表以显示已安装的客户端,例如Facebook 应用程序并一直在使用它(used 属性显示了这一点)。所以我想这样显示列表:

Ivan Drew
Facebook
21/12/2014

John Roberts
Facebook
09/11/2014

我用两个 ng-repeat 创建了我的 html,看起来像这样:

<div class="client-info" ng-repeat="client in clients">
    <div ng-repeat="app in client.apps | filter: { name: 'Facebook', used: 'Y' }">
        {{ client.name }}<br />
        {{ app.appName }}<br />
        {{ app.installedDate }}<br />
    </div>
</div>

所以,正如我上面所说,这可以按预期工作,但是当您有大量信息(例如,1000 个客户至少每个有 5 个应用程序)时,我会检查它,它会变得很滞后。所以我检查了这个输出是什么,看到.client-info 元素显示(当然是空的),即使没有一个应用程序符合要求。 我在考虑如何优化它,但现在做不到。

有人知道如何让它变得更好吗?

提前致谢! :)

【问题讨论】:

  • 为了提高性能,您只需将Angular 完全替换为React.js

标签: javascript arrays angularjs filter angularjs-ng-repeat


【解决方案1】:

您有多种选择来提高性能。

仅绑定一次,使用 :: 语法(假设您不需要 2 路绑定)。

<div ng-repeat="app in ::client.apps | filter: { name: 'Facebook', used: 'Y' }">
    {{ ::client.name }}<br />
    {{ ::app.appName }}<br />
    {{ ::app.installedDate }}<br />
</div>

如果您使用的是 Angular

如果您真的只是像示例中那样通过硬编码过滤器进行过滤,您可以在数据到达视图之前过滤数据(在控制器中,或者更好的是,在检索数据的服务中)。这将防止 Angular 在每个摘要循环中重新评估您的过滤器。

您还可以使用track by 语法来提高性能。在这种情况下,我猜测的是 client.name(但这只是一个猜测):

ng-repeat="app in ::client.apps | filter: { name: 'Facebook', used: 'Y' } track by client.name

如果客户端名称不是唯一的,您可能需要进行调整。

我怀疑只实现一次绑定会给您带来显着的性能提升。

【讨论】:

  • 是的,我考虑过在将数组显示在控制器中之前对其进行过滤,如您所说。但是我的情况似乎存在问题 - 我需要返回过滤的客户列表和每个联系人过滤的应用程序列表,在我看来,这有点问题。在这种情况下,我将只显示信息而不在 html 中执行任何操作。我知道bindonce 功能,但数据会更新,所以我需要保持观察者......我知道如果没有这样的东西我会使用它。
【解决方案2】:

在您的控制器中,您可以过滤然后将其发送到视图,而不是发送整个对象。像这样的东西;

        function filter(element, appName) {
            var retArr = [];
            if(element.length > 0) {
                for(i = 0 ; i < element.length ; i++){                        
                    var arrAppend = element[i];

                    if(arrAppend.apps.length > 1) {
                        for(j = 0 ; j < arrAppend.apps.length ; j++) {
                            if(arrAppend.apps[j]['appName'] == appName && arrAppend.apps[j]['used'] == 'Y') {
                                retArr.push(arrAppend);
                                break;
                            }
                        }
                    }

                }
            }

            return retArr;

        }
        $scope.clients = filter($scope.clients, 'Facebook'));

或者如果你有 jquery,你可以使用 $.grep

【讨论】:

    猜你喜欢
    • 2016-07-12
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 2015-11-14
    • 2017-12-23
    • 1970-01-01
    相关资源
    最近更新 更多