控制器性能比较中的自定义过滤器与过滤器功能 [英] Custom filter vs filter function in controller performance comparison

查看:22
本文介绍了控制器性能比较中的自定义过滤器与过滤器功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose I have an array of 5000 objects (with boolean values) which I have to ng-repeat in the template:

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

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

Now, I want to filter this ng-repeated array on the basis of a dynamic variable, say 'show_filter', which I am setting elsewhere.

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

If 'show_filter' is set to 'all' I want to show all the objects. If it is set to false (the boolean value) then I want to show objects with 'value' key set to false. Same goes for when 'show_filter' is set to true.

所以,有两种方法:

1.构建自定义过滤器:

我会为这样的过滤任务编写一个自定义过滤器:

I would write a custom filter for the filtering task like this:

过滤器:

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,这让我相信它的效率很低.虽然我不确定这两种方式哪个更快.

Which of the above two methods will be faster? I have seen the custom filter code execute everytime for each digest loop and not only for changes made to $scope.show_filter, which leds me to believe its quite inefficient. Although I am not sure which is faster between the two ways.

推荐答案

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

Both functions will be called in every digest cycle. That's somewhat obvious for the second function. The return value of filterObjects(arr) could be different on every call.

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

It's not so obvious why a filter would be called in every digest cycle. The documentation states the following:

过滤器函数应该是纯函数,这意味着它应该是无状态和幂等的.Angular 依赖于这些属性,并且仅在函数的输入发生变化时才执行过滤器.

The filter function should be a pure function, which means that it should be stateless and idempotent. Angular relies on these properties and executes the filter only when the inputs to the function change.

所以如果 arrshow_filter 都没有改变,那么过滤器就不应该被调用,对吧?但这里有一个问题:检测 arr 中的变化代价高昂.

So if neither arrnor show_filter change then the filter shouldn't be called, right? But here's the catch: Detecting a change in arr is costly.

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

Angular has to make a copy of the array to compare it with the current content. Even if nothing has changed, every single item has to be compared. And if the items are objects every single property of them has to be compared. Directly calling a filter instead is much cheaper. And that's what Angular does when a filter is applied to an array (or object).

要加速应用程序,您有两种选择.第一个是仅在必要时过滤数组并将过滤后的数组公开给 ng-repeat.例如.如果您可以输入一个用于过滤数组的值,则在该值更改时过滤该数组.

To speed up the application you have two choices. The first one is to filter the array only when it's necessary and to expose the filtered array to ng-repeat. E.g. if you can enter a value by which the array will be filtered, then filter the array whenever that value changes.

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

The second alternative can be used if both the array and the filter don't change (so not in your case). Then you can use one-time binding:

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

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

That's useful when you have a fixed set of items and want to sort them by name e.g. The filter will be called only once in that case.

这篇关于控制器性能比较中的自定义过滤器与过滤器功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆