AngularJS改进了嵌套数组的过滤

AngularJS improve filtering for nested arrays

本文关键字:数组 过滤 嵌套 AngularJS      更新时间:2023-09-26

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

$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元素(当然是空的),即使没有一个应用程序符合要求。我正在考虑如何优化它,但现在还不够。

有人有一些想法如何让它变得更好吗?

提前感谢! :)

您可以通过多种方式来提高性能。

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

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

如果您使用的是 Angular <1.3,则需要具有不同语法的第三方绑定一次库。

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

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

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

如果客户端名称不唯一,则可能需要对其进行调整。

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

在控制器中,您可以过滤然后发送它以供查看,而不是发送整个对象。像这样的东西;

        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