【问题标题】:Custom filter vs filter function in controller performance comparison控制器性能比较中的自定义过滤器与过滤器功能
【发布时间】:2016-02-23 19:21:58
【问题描述】:

假设我有一个包含 5000 个对象(带有布尔值)的数组,我必须在模板中 ng-repeat:

$scope.arr = [
    {
        "value": true
    },
    {
        "value": false
    },
    {
        "value": false
    }
    //and so on
]

现在,我想根据一个动态变量过滤这个ng-repeated 数组,比如我在别处设置的“show_filter”。

如果 'show_filter' 设置为 'all' 我想显示所有对象。如果它设置为 false(布尔值),那么我想显示将“value”键设置为 false 的对象。 'show_filter' 设置为 true 时也是如此。

所以,有两种方法:

1.构建自定义过滤器:

我会为过滤任务编写一个自定义过滤器,如下所示:

过滤器:

app.filter('filterArr', function() {
    return function(arr, show_filter) {
        var filtered_arr = [];
        if(show_filter != 'All') { //if show_filter is a boolean value
            for(var i = 0; i < arr.length; i++) {
                if(arr[i].value == show_filter) { 
                    filtered_arr.push(arr[i]);
                }
            }
            return filtered_arr;
        }
        else {
            return arr; //return the entire array if show_filter is set to 'All'
        }
    }
})

模板:

obj in arr | filterArr : show_filter

2。在控制器中编写过滤函数:

过滤器:

$scope.filterObjects = function(arr) {
    var filtered_arr = [];
    if($scope.show_filter != 'All') { //if $scope.show_filter is a boolean value
        for(var i = 0; i < arr.length; i++) {
            if(arr[i].value == $scope.show_filter) { 
                filtered_arr.push(arr[i]);
            }
        }
        return filtered_arr;
    }
    else {
        return arr; //return the entire array if show_filter is set to 'All'
    }
}

模板:

obj in filterObjects(arr)

以上两种方法中哪一种会更快?我已经看到自定义过滤器代码每次都会针对每个摘要循环执行,而不仅仅是对$scope.show_filter的更改,这让我相信它相当低效。虽然我不确定这两种方式哪个更快。

【问题讨论】:

  • 你有两个相同的函数,你问哪个最快?如果您的意思是哪个被调用的次数最少,那么您可能已经回答了自己的问题?
  • 第二个函数不知道调用了多少次。
  • 最快的替代方法是将过滤后的数组公开给ngRepeat。第二个函数必须在每个摘要循环中调用。
  • 数组是根据外部变量过滤的,外部变量可以通过事件随时设置。所以,我不认为我可以有一个预先过滤的数组。我认为最好的方法是在外部变量上应用 watch 并在 watch 的回调中过滤数组。你怎么看?
  • 我就是这个意思。

标签: javascript angularjs performance filter angularjs-filter


【解决方案1】:

这两个函数将在每个摘要循环中调用。这对于第二个功能来说有些明显。 filterObjects(arr) 的返回值在每次调用时都可能不同。

为什么在每个摘要循环中都会调用 filter 并不是很明显。文档说明如下:

filter函数应该是纯函数,也就是说它应该是无状态和幂等的。 Angular 依赖这些属性,仅在函数的输入发生变化时才执行过滤器。

因此,如果 arr 和 show_filter 均未更改,则不应调用过滤器,对吗?但这里有一个问题:检测arr 的变化代价高昂。

Angular 必须复制该数组以将其与当前内容进行比较。即使没有任何变化,也必须比较每一个项目。如果项目是对象,则必须比较它们的每个属性。相反,直接调用过滤器要便宜得多。这就是 Angular 在将过滤器应用于数组(或对象)时所做的事情。

要加快应用程序的速度,您有两种选择。第一个是仅在必要时过滤数组并将过滤后的数组公开给ng-repeat。例如。如果您可以输入一个值来过滤数组,那么只要该值发生变化就过滤数组。

如果数组和过滤器都没有改变(所以不是你的情况),可以使用第二种选择。然后就可以使用一次性绑定了:

<li ng-repeat="item in ::array | filter">

当您有一组固定的项目并希望按名称对它们进行排序时,这很有用,例如在这种情况下,过滤器只会被调用一次。

【讨论】:

  • '直接调用过滤器更便宜'。这意味着第一种方法还是第二种方法?此外,不能将一种校正、过滤器应用于对象。尽管如此,感谢您清理了许多事情!
  • 这适用于自定义过滤器(第一种方法)。过滤器可以应用于所有内容。想想datefilter(日期是一个对象)或json 过滤器,它只对对象有意义。顺便说一句,数组也是一个对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 2013-09-18
  • 2015-02-24
  • 1970-01-01
  • 2015-08-01
  • 1970-01-01
相关资源
最近更新 更多