angular内置过滤器-filter

这篇文章来讲解一下angular内置的filter过滤器.

没错,这个过滤器的名字,就叫'filter',虽然自定义过滤器也是使用module.filter()...但是不要混淆了,这个filter就是过滤器的名字~

这个过滤器是干嘛的呢? 它的作用是: '从数组中过滤出需要的项,放入新的数组并返回这个新数组。'

一.用在html模板里:

因为是用来过滤数组,所以这个过滤器基本上都用在ng-repeat指令上,比如:

<div ng-repeat="list in lists | filter : expression : comparator"></div>

filter过滤器会对lists数组进行过滤返回一个新的数组,过滤的方式取决于后面两个参数: expression : comparator

*在最早的angular版本中,是没有第二个参数的.

本篇的例子都是基于下面这段html和js的:

可以在这里输入各个例子的代码进行调试,查看结果:

http://jsfiddle.net/fxgzxuou/

<!DOCTYPE html>
<html ng-app="app">
<head>
  <title>filter过滤器</title>
  <meta charset="utf-8">
  <script src="../../angular.min.js"></script>
  <style type="text/css">
    * {
      font-family:'MICROSOFT YAHEI'
    }
    b {
      font-weight:normal; color:#169FE7;
    }
  </style>
</head>
<body >
  <div ng-controller="ctrl">
    <ul>
      <li ng-repeat="list in lists|filter:condition:mode">
        <span><b>name:</b>{{list.name}}</span>
        <br/>
        <span><b>age:</b>{{list.age}}</span>
      </li>
    </ul>
  </div>
</body>
</html>
var app = angular.module('app',[]);
app.controller('ctrl',function($scope,$filter){
    $scope.lists = [
      {name:'code_bunny',age:12},
      {name:'code_dog',age:3},
      {name:'code_cat',age:22},
      {name:'white_bunny_1',age:11},
      {name:'white_bunny_2',age:11},
      {name:'black_bunny',age:9},
      {name:'mi_bunny_1',age:2},
      {name:'mi_bunny_2',age:10},
      {name:'mi_bunny_2',age:1}
    ];
//在这里定义$scope.condition和$scope.mode })

在ctrl控制器下,有lists这样一组数组,在后面我们会通过改变参数condition和mode,来改变过滤条件,并观察结果.在没有任何过滤条件的时候,它全部显示:

1.expression:

(1).字符串: 遍历数组每个对象的所有属性,凡属性中包含了expression字符串的,则这个对象被过滤出来.不区分大小写.

eg 1.1.0:

    /*普通模式,第三个参数为false:*/
    $scope.mode=false;
    //1.一个字符串:匹配属性中带有这个字符串的内容
    $scope.condition='1';

结果: 将所有name属性或者age属性中带有'1'的项都过滤出来了:

(2).json对象:

让json对象里的属性值和数组中的属性值一一对比过滤,过滤的规则还是是否包含.比如 {name:"M", phone:"1"} 对象,会过滤出name属性值中带有M的,并且phone属性值中带有1的对象. 

另外,{$:''}这个$属性,表示过滤任何属性.当使用{$:'1'}的时候,就相当于使用字符串'1'

eg 1.2.0:

    /*普通模式,第三个参数为false:*/
    $scope.mode=false;
    //2.一个对象: 相当于$scope.condition='1';
    $scope.condition={$:'1'};

结果:(和$scope.condition='1'的时候一样)

eg 1.2.1:

    /*普通模式,第三个参数为false:*/
    $scope.mode=false;

    //3.一个对象: 匹配name属性值中带有1的
    $scope.condition={name:'1'};

结果: (过滤出name属性中带有'1'的项)

 

eg 1.2.2:

    /*普通模式,第三个参数为false:*/
    $scope.mode=false;
    //4.一个对象: 匹配name属性值中带有bunny,age属性值中带有1的
    $scope.condition={name:'bunny',age:1};

结果: (过滤出name属性值中带有bunny,age属性值中带有1的)

(3).函数: 

function(value){...}

数组中的每一项都会被作为函数的参数value传入,然后执行这个函数,根据返回值来判断是否被过滤.

eg 1.3.0: 过滤出name属性值中既有m,又有b的(不一定要mb连在一起)

    $scope.mode=false;
    /*匹配一个函数*/
    $scope.condition = function(value){
      if(value.name.indexOf('m')>=0 && value.name.indexOf('b')>=0){
        return true
      }
    };

结果:

*在这种情况下,既然已经自己定义了过滤的模式,就没有必要再定义第三个参数了. 

 

2.comparator:

(1)true:严格匹配,不是匹配属性值是否包含了过滤条件,而是必须===全等,大小写也严格区分.

eg 2.1.0: 在eg1.1.0的基础上,把第三个参数mode改为true:

    /*严格模式,第三个参数为true:*/
    $scope.mode=true;
    //一个字符串:匹配属性==='1'
    $scope.condition='1';

结果是空,因为严格过滤是===匹配,所以,数值1不==='1',

改成:

    /*严格模式,第三个参数为true:*/
    $scope.mode=true;
    //一个字符串:匹配属性===1
    $scope.condition=1;

结果:

 

eg 2.1.1: 在eg1.2.0的基础上,把第三个参数mode改为true,并且把'1'改为1:

    /*严格模式,第三个参数为true*/
    $scope.mode=true;

    //6.严格匹配对象: 匹配属性值===1的
    $scope.condition={$:1};

结果同eg 2.1.0

 

eg 2.1.2:

    /*严格模式,第三个参数为true*/
    $scope.mode=true;
    //7.严格匹配对象: name值==='white_bunny_1',age值===11的
    $scope.condition={name:'white_bunny_1',age:11};

结果:

(2)函数:

function(actual,expected){
  //actual是对象实际的值
  //expected是过滤条件的值
return ...
}

这个函数是用来自己定义过滤的模式的,之前已经说过,如果不定义第二个参数,那么它是按照'是否包含'来进行过滤的,如果第二个参数是true, 那么它是按照'是否全等'来进行过滤的.而自定义函数,则是按照自定义的规则来进行过滤.

函数接受两个参数:

actual:对象的实际属性值

expected:第一个参数中定义的过滤条件值

eg 2.2.0:

    //9.深度匹配对象:{name:'mi_bunny_1',age:'10'}
    //要求过滤的方式是比较是否相等,但不比较数据格式.比如这里的'10'==10,可以被过滤出来
    $scope.mode=function(actual,expected){
      if(actual==expected){
        return true
      }
    };
    $scope.condition={name:'mi_bunny_2',age:'10'};

结果:

这里自定义了一个过滤方式,是比较是否相等,而不是是否全等,属性值的格式可以不同.

eg 2.2.1:

    //10.深度匹配字符串:'11':匹配年龄或者name==11的
    $scope.mode=function(actual,expected){
      if(actual==expected){
        return true
      }
    };
    $scope.condition='11';

结果:

过滤条件改成'11',一样遵循这个函数的过滤方式

*注意,通过第二个参数自定义函数来自定义过滤条件,它定义的过滤条件是针对所有的属性的,不能为各个属性指定自己的过滤方式,如果是要为某个属性自定义过滤方法,应该使用第一个参数的函数形式,类似于eg1.3.0

eg 2.2.2:

在filter的官方api里有一个这样的demo:

http://www.ngnice.com/docs/api/ng/filter/filter

Any: <input ng-model="search.$"> <br>
Name only <input ng-model="search.name"><br>
Phone only <input ng-model="search.phone"><br>
Equality <input type="checkbox" ng-model="strict"><br>
<table id="searchObjResults">
  <tr><th>Name</th><th>Phone</th></tr>
  <tr ng-repeat="friendObj in friends | filter:search:strict">
    <td>{{friendObj.name}}</td>
    <td>{{friendObj.phone}}</td>
  </tr>
</table>

这个demo使用的是严格过滤模式,也就是第二个参数是true,但是这样会出现一种bug:

一开始没有输入Name only和Phone only的时候,search.name和search.phone是没有的,不是说{name:'',phone:''},而是{}就是空的,
所以当只输入name项以后变为{name:'John'},这个时候可以匹配到name值为John的数据,然后我phone项后变为{name:'John',phone:'555-1276'},也是可以匹配到正确的数据的.
但是,当我清空phone以后,它会变为{name:'John',phone:''},所以数据中就不再有能够匹配到的项了.所以,这个例子,一旦输入过某项再清空,就无法再正确使用严格模式来匹配数据了.

所以,我将第三个参数true改为一个自定义函数,使得属性值为''的情况一样能够被过滤出来:

http://jsfiddle.net/m0x9fn0z/

核心代码:

    $scope.mode = function(actual,expected){
      if(actual===expected || expected==''){
        return true
      }
      else {
        return false
      }
    }

 

(3)false || undefined: 默认情况,没有第三个参数,不进行严格匹配

 

二.直接在js里使用,需要注入$filter依赖:

var newArry = $filter('filter')(array, expression, comparator)

第一个参数array就是需要被过滤的数组,后面两个参数用法都同上. 

eg 3.1.0:

    //直接在js里面使用:
    var newArray = $filter('filter')($scope.lists, 'black', false);
    console.log(newArray);

结果: (不影响视图)

 

posted @ 2014-10-16 16:46  诗&远方  阅读(11829)  评论(2编辑  收藏  举报