这篇文章来讲解一下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的:
可以在这里输入各个例子的代码进行调试,查看结果:
<!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改为一个自定义函数,使得属性值为''的情况一样能够被过滤出来:
核心代码:
$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);
结果: (不影响视图)