《AngularJS实战》——3.1 模板中的过滤器

简介:

本节书摘来自华章出版社《AngularJS实战》一 书中的第3章,第3.1节,作者:陶国荣,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.1 模板中的过滤器

过滤器的主要功能是格式化数据,这里所说的数据,既包括视图模板中的表达式,也包括控制器中的数组或对象。开发人员不仅可以方便地调用Angular中提供的过滤器,还可以自定义属于自己的过滤器。接下来,我们通过一些实用的案例,来介绍过滤器的强大功能。

3.1.1 排序方式过滤

在介绍排序(orderBy)过滤器之前,先来了解一下过滤器的使用格式。在Angular中,过滤器有3种调用方式,分别为单个过滤器、多个过滤器和带参数的过滤器,它们分别对应不同的使用格式,下面分别进行介绍。
1.?单个过滤器
单个过滤器常用于视图模板的表达中,它的使用格式非常简单,调用格式如下所示。
{{表达式 | 过滤器名}}
在上述代码中,“{{}}”双花括号为表达式标记,在括号中,“|”为管道符,通过该符号分成前后两部分,前部分为需要被格式化的表达式,后部分为过滤器的名称,示例代码如下。
{{8.88 | currency}}
代码执行后的结果为:$8.88,即在表达式前添加了一个“$”符号。在上述代码中,数值8.88为表达式,而currency则为货币过滤器。
2.?多个过滤器
在视图模板的表达式中,除使用单个过滤器之外,还可以同时调用多个过滤器,格式如下。
{{表达式 | 过滤器名1 | 过滤器名2 | ...}}
在上述代码中,多个过滤器名使用管道符“|”隔开,其他内容与单个过滤器的使用方法相同。
3.?带参数过滤器
当然,无论是单个过滤器还是多个过滤器,它们都可以在调用时带参数,调用格式如下。
{{表达式 | 过滤器名1 :参数1 :参数2 :...}}
在上述代码中,过滤器的参数跟随在过滤器名称的后面,通过“:”来进行识别,多个参数之间使用“:”进行分隔,多个过滤器同样可以带多个参数,示例代码如下。
{{8.8800 | number:1}}
代码执行后的结果为8.9,虽然表达式值中有4位小数,但由于“number”过滤器中小数位的参数值为1,因此,在显示时只能保留一位。在保留时,按四舍五入的方式进行舍取,所以,最终数值8.8800经过过滤器格式化后,变成8.9。
在介绍完过滤器的多个调用格式之后,我们再来详细说明排序过滤器的用法,该过滤器的功能是按指定的一个或多个对象属性名称进行数据过滤的,通过排序过滤器,不仅可以获取按照指定属性名称排序后的数据,而且还能通过过滤器设置数据返回时的记录总数量。
接下来,我们通过一个完整的示例来演示排序过滤器使用的过程。
示例3-1 排序方式过滤
(1)功能描述
在页面的视图模板中,调用排序过滤器,将显示的数据按“score”属性值降序进行排列,并且只显示前3条数据记录。
(2)实现代码
新建一个HTML文件3-1.html,加入如代码清单3-1所示的代码。
代码清单3-1 排序方式过滤

<!doctype html>
<html ng-app="a3_1">
<head>
    <title>排序(orderBy)方式过滤</title>
    <script src="../Script/angular.min.js"
            type="text/javascript"></script>
    <style type="text/css">
        body {
            font-size: 12px;
        }
        ul {
            list-style-type: none;
            width: 408px;
            margin: 0px;
            padding: 0px;
        }
            ul li {
                f?loat: left;
                padding: 5px 0px;
            }
            ul .odd {
                color: #0026ff;
            }
            ul .even {
                color: #ff0000;
            }
            ul .bold {
                font-weight: bold;
            }
            ul li span {
                width: 52px;
                f?loat: left;
                padding: 0px 10px;
            }
            ul .focus {
                background-color: #cccccc;
            }
    </style>
</head>
<body>
    <div ng-controller="c3_1">
        <ul>
            <li ng-class="{{bold}}">
                <span>序号</span>
                <span>姓名</span>
                <span>性别</span>
                <span>年龄</span>
                <span>分数</span>
            </li>
            <li ng-repeat=" stu in data | orderBy: '-score' 
                        | limitTo: 3"
                ng-class-odd="'odd'"
                ng-class-even="'even'">
                <span>{{$index+1}}</span>
                <span>{{stu.name}}</span>
                <span>{{stu.sex}}</span>
                <span>{{stu.age}}</span>
                <span>{{stu.score}}</span>
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        var a3_1 = angular.module('a3_1', []);
        a3_1.controller('c3_1', ['$scope', function ($scope) {
            $scope.bold = "bold";
            $scope.data = [
            { name: "张明明", sex: "女", age: 24, score: 95 },
            { name: "李清思", sex: "女", age: 27, score: 87 },
            { name: "刘小华", sex: "男", age: 28, score: 86 },
            { name: "陈忠忠", sex: "男", age: 23, score: 97 }
            ];
        }]);
    </script>
</body>
</html>

(3)页面效果
执行HTML文件3-1.html,最终实现的页面效果如图3-1所示。

9b8a69e3e8e8ef09741ffb73f8b28ee478c89ba7

(4)源码分析
在本示例的源码中,当视图中的模板通过“ng-repeat”指令绑定控制器中的数据时,调用了orderBy过滤器,代码如下所示。

stu in data | orderBy: '-score' | limitTo: 3

在上述代码中,第一个管道符“|”的左侧为控制器中的数组data,右侧为过滤器的名称“orderBy”,表示排序过滤器,紧接着的冒号右侧为该过滤器调用时的参数,“-score”为排序时指定的属性名称,即按该属性名排序,默认时为升序,在属性名前添加“-”符号后,则变为降序。
第二个管道符“|”的右侧为过滤器的名称“limitTo”,用于设置数据显示时的记录总量,具体的总量值通过冒号后的参数值来指定,本示例为3,表示只显示3条记录。

3.1.2 匹配方式过滤

与排序方式不同,匹配方式是将字符参数与列表中的各个成员属性值相匹配,如果包含该字符参数值,则显示该条列表记录。匹配时,不区分字符的大小写。常见的匹配方式有下列几种。
1.?通过f?ilter过滤器直接匹配包含字符参数的数据
这种方式只需要在调用f?ilter过滤器时,添加一个需要匹配的字符参数,调用格式如下。
{{数据 | f?ilter:'匹配字符'}}
在上述调用格式代码中,匹配字符是过滤器f?ilter的参数,一旦添加该参数之后,将在整个数据的属性中查找匹配项,找到后,则显示,否则不显示。字符内容必须加引号,如以下代码所示。

{{data | f?ilter:80}}

上述代码表示,在data数据的各个属性中,查找包含“80”内容的记录。
2.?在字符参数中使用对象形式匹配指定属性的数据
如果在过滤数据时已经明确了数据匹配的属性范围,也可以在字符参数中通过对象的形式指定匹配的属性名称,调用格式如下。
{{数据 | f?ilter:对象}}
在上述调用格式的对象中,过滤器参数是一个对象,通过key/value方式声明属性名称和匹配的字符内容,如果属性名称为“$”,则表示在全部属性中查找,代码如下。

{{data | f?ilter:{score:80}}}和{{data | f?ilter:{$:80}}}

在上述代码中,前者仅是在“score”属性列中匹配值为80的数据记录,后者则是在全部属性列中匹配数据记录,后者相当于下列代码。

{{data | f?ilter:80}}

3.?在字符参数中使用自定义函数匹配相应数据
在f?ilter过滤器的字符参数中,除使用对象外,还可以直接调用自定义的函数名,处理相对复杂的数据匹配情况,调用格式如下。
{{数据 | f?ilter:函数名称}}
在上述调用格式中,过滤器的参数为函数名称,即自定义的匹配数据的函数名。接下来,通过一个完整的示例来介绍在f?ilter过滤器的形参中,使用自定义函数来匹配数据的过程。
示例3-2 匹配方式过滤
(1)功能描述
在示例3-1的基础上,调用匹配过滤器,查询“score”属性值大于85且小于90的数据记录,并将数据显示在视图模板中。
(2)实现代码
新建一个HTML文件3-2.html,加入如代码清单3-2所示的代码。
代码清单3-2 匹配方式过滤

<!doctype html>
<html ng-app="a3_2">
<head>
    <title>匹配(f?ilter)方式过滤</title>
    <script src="../Script/angular.min.js"
            type="text/javascript"></script>
    <style type="text/css">
        body {
            font-size: 12px;
        }
        ul {
            list-style-type: none;
            width: 408px;
            margin: 0px;
            padding: 0px;
        }
            ul li {
                f?loat: left;
                padding: 5px 0px;
            }
            ul .odd {
                color: #0026ff;
            }
            ul .even {
                color: #ff0000;
            }
            ul .bold {
                font-weight: bold;
            }
            ul li span {
                width: 52px;
                f?loat: left;
                padding: 0px 10px;
            }
            ul .focus {
                background-color: #cccccc;
            }
    </style>
</head>
<body>
    <div ng-controller="c3_2">
        <ul>
            <li ng-class="{{bold}}">
                <span>序号</span>
                <span>姓名</span>
                <span>性别</span>
                <span>年龄</span>
                <span>分数</span>
            </li>
            <li ng-repeat=" stu in data | f?ilter:f?indscore"
                ng-class-odd="'odd'"
                ng-class-even="'even'">
                <span>{{$index+1}}</span>
                <span>{{stu.name}}</span>
                <span>{{stu.sex}}</span>
                <span>{{stu.age}}</span>
                <span>{{stu.score}}</span>
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        var a3_2 = angular.module('a3_2', []);
        a3_2.controller('c3_2', ['$scope', function ($scope) {
            $scope.bold = "bold";
            $scope.data = [
            { name: "张明明", sex: "女", age: 24, score: 95 },
            { name: "李清思", sex: "女", age: 27, score: 87 },
            { name: "刘小华", sex: "男", age: 28, score: 86 },
            { name: "陈忠忠", sex: "男", age: 23, score: 97 }
            ];
            $scope.f?indscore = function (e) {
                return e.score > 85 && e.score < 90;
            }
        }]);
    </script>
</body>
</html>

(3)页面效果
执行HTML文件3-2.html,最终实现的页面效果如图3-2所示。

c3334310e5557edf2af3f75098852890795906a8

(4)源码分析
在本示例的源代码中,为了查找“分数”在85到90之间的数据,在示例的控制器代码中,先添加了一个名为f?indscore的自定义函数,并在添加函数时,定义了一个名为“e”的形参,该形参的值为数据源对象;然后,根据这个数据源对象中的“score”属性值,通过逻辑运算符返回“分数”在85到90之间的记录数据。
最后,在本示例中的视图模板中,当通过f?ilter过滤器匹配数据时,直接将f?indscore函数名作为过滤器的参数,此时,“data”对象已作为实参自动传递给f?indscore函数的形参“e”中,函数接收后,根据“data”对象中的“score”属性值,将“分数”在85到90之间的数据显示在视图的模板中。

3.1.3 自定义过滤器

除调用Angular中自带的过滤器外,还可以自己定义过滤器。定义过滤器的方法很简单,只需要在页面模块中注册一个过滤器的构造方法,该方法将返回一个以输入值为首个参数的函数,在函数体中实现过滤器的功能。接下来,我们通过一个完整的示例来演示自定义过滤器的过程。
示例3-3 自定义过滤器
(1)功能描述
在示例3-1的基础上,调用自定义的过滤器,查询“age”属性值大于22且小于28的可选性别的数据记录,并将数据显示视图模板中。
(2)实现代码
新建一个HTML文件3-3.html,加入如代码清单3-3所示的代码。
代码清单3-3 自定义过滤器

<!doctype html>
<html ng-app="a3_3">
<head>
    <title>自定义过滤器</title>
    <script src="../Script/angular.min.js"
            type="text/javascript"></script>
    <style type="text/css">
        body {
            font-size: 12px;
        }
        ul {
            list-style-type: none;
            width: 408px;
            margin: 0px;
            padding: 0px;
        }
            ul li {
                f?loat: left;
                padding: 5px 0px;
            }
            ul .odd {
                color: #0026ff;
            }
            ul .even {
                color: #ff0000;
            }
            ul .bold {
                font-weight: bold;
            }

            ul li span {
                width: 52px;
                f?loat: left;
                padding: 0px 10px;
            }
            ul .focus {
                background-color: #cccccc;
            }
    </style>
</head>
<body>
    <div ng-controller="c3_3">
        <ul>
            <li ng-class="{{bold}}">
                <span>序号</span>
                <span>姓名</span>
                <span>性别</span>
                <span>年龄</span>
                <span>分数</span>
            </li>
            <li ng-repeat=" stu in data | young:0"
                ng-class-odd="'odd'"
                ng-class-even="'even'">
                <span>{{$index+1}}</span>
                <span>{{stu.name}}</span>
                <span>{{stu.sex}}</span>
                <span>{{stu.age}}</span>
                <span>{{stu.score}}</span>
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        var a3_3 = angular.module('a3_3', []);
        a3_3.controller('c3_3', ['$scope', function ($scope) {
            $scope.bold = "bold";
            $scope.data = [
            { name: "张明明", sex: "女", age: 24, score: 95 },
            { name: "李清思", sex: "女", age: 27, score: 87 },
            { name: "刘小华", sex: "男", age: 28, score: 86 },
            { name: "陈忠忠", sex: "男", age: 23, score: 97 }
            ];
        }]);
        a3_3.f?ilter('young', function () {
            return function (e, type) {
                var _out = [];
                var _sex = type ? "男" : "女";
                for (var i = 0; i < e.length; i++) {
                    if (e[i].age > 22 && e[i].age < 28 && 
                        e[i].sex == _sex)
                        _out.push(e[i]);
                }
                return _out;
            }
        });
    </script>
</body>
</html>

(3)页面效果
执行HTML文件3-3.html,最终实现的页面效果如图3-3所示。
(4)源码分析
在本示例的控制器代码中,为了实现开发需求,先通过页面模块“a3_3”调用“f?ilter”方法,创建了一个名为“young”的自定义过滤器,该过滤器将通过return语句返回一个函数。在函数体中,通过代码编写,实现对应需求的功能开发。接下来,我们重点分析一下这个返回的函数。
首先,在这个函数中,定义了两个形参“e”和“type”,前者“e”参数在调用过滤器时,将会被需要过滤的数据自动注入,关于自动注入的概念,将会在第4章中进行详细介绍。后者“type”参数,将会在调用过滤器时,通过冒号形式向过滤器传递实参。

38f3bf4daf7304b15e4cdbea019bbcd5813a4bd5

其次,在函数体中,由于本示例过滤的数据是一个数组,因此,先定义一个名为“_out”的空数组,并将传来的“type”性别类型参数进行字符转化,保存在变量“_sex”中;然后,对自动注入的“e”数组中的数据进行遍历,在遍历过程中,检测各项元素的“年龄”属性值是否在“22~28”范围之间,并且“性别”属性值是否与变量“_sex”相符。如果这两项条件都满足,则将该项数组元素添加至空数组“_out”中,其核心代码如下所示。
...省略部分代码

var _out = [];
var _sex = type ? "男" : "女";
for (var i = 0; i < e.length; i++) {
     if (e[i].age > 22 && e[i].age < 28 && e[i].sex == _sex)
         _out.push(e[i]);
}
...省略部分代码

最后,在函数体结束时,通过调用return语句,将包含符合过滤条件数据的数组“_out”返回给自定义过滤器“young”。当在视图模块中调用过滤器“young”时,将执行返回函数体中代码,并返回符合条件的数据,最终实现根据需求过滤数据的功能。

相关文章
|
JavaScript 容器 数据挖掘
Angularjs 与三方js插件配合使用,并通过模板动态解析angularjs 语法
在一个静态见面上做数据分析,由于前后端分离 前端使用Angularjs框架,后端使用RESTFUL,如图
2673 0
|
Web App开发 JavaScript 前端开发
|
JSON 数据格式
|
Web App开发 JavaScript