本节书摘来自华章出版社《AngularJS实战》一 书中的第2章,第2.3节,作者:陶国荣,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2.3 Angular中的模板
Angular自身提供了一整套完整的模板系统,配合$scope对象和数据双向绑定机制,将页面纯静态元素经过行为、属性的添加和格式的转换,最终变成在浏览器中显示的动态页。
在模板系统中,可以包含Angular的指令、数据绑定、表单控件和过滤器,同时,在处理复杂程序时,可以构建多个模板页面作用于视图层。在主页中,再通过包含(include)的方式加载这些零散的模板页。这样做的好处在于,一次定义可多处调用,增加代码的重复使用,减少维护成本。
2.3.1 构建模板内容
构建模板的内容是使用模板功能的前提,一般通过下列几种方式来实现。
直接在页面中添加元素和Angular指令,依赖控制器中构建的属性和方式绑定模板中的元素内容和事件,实现应用需求。
通过“type”类型为“text/ng-template”的
<!doctype html>
<html ng-app="a2_9">
<head>
<title>构建模板内容</title>
<script src="../Script/angular.min.js"
type="text/javascript"></script>
</head>
<body>
<script type="text/ng-template" id="tplbase">
姓名:{{ name }},<br />邮箱:{{email}}
</script>
<div ng-include src="'tplbase'" ng-controller="c2_9"></div>
<script type="text/javascript">
var a2_9 = angular.module('a2_9', []);
a2_9.controller('c2_9', ['$scope', function ($scope) {
$scope.name = '陶国荣';
$scope.email = 'tao_guo_rong@163.com';
}]);
</script>
</body>
</html>
(3)页面效果
执行HTML文件2-9.html,最终实现的页面效果如图2-9所示。
(4)源码分析
在本示例的源码中,先添加一个“type”类型为“text/ng-template”的
2.3.2 使用指令复制元素
在构建模板内容的过程中,有时需要反复将不同的数据加载到一个元素中,例如,通过
元素绑定一个数组的各成员。此时,可以使用“ng-repeat”指令,它的功能是根据绑定数组成员的数量,复制页面中被绑定的元素,并在复制过程中添加元素相应的属性和方法,通过这种方式,实现数组数据与元素绑定的过程。在使用“ng-repeat”指令复制元素的过程中,还提供了几个非常实用的专有变量,可以通过这些变量来处理显示数据时的各种状态。这些变量的功能分别如下。
$f?irst,该变量表示记录是否是首条,如果是则返回true,否则返回false。
$last,该变量表示记录是否是尾条,如果是则返回true,否则返回false。
$middle,该变量表示记录是否是中间条,如果是则返回true,否则返回false。
$index,该变量表示记录的索引号,其对应的值从0开始。
接下来,通过一个示例来演示使用“ng-repeat”指令复制元素的过程。
示例2-10 使用指令复制元素
(1)功能描述
在页面中,通过元素显示一个数组中的全部成员数据,并且在显示数据时列出当条记录是否为“首条”和“尾条”记录的状态信息。
(2)实现代码
新建一个HTML文件2-10.html,加入如代码清单2-10所示的代码。
代码清单2-10 使用指令复制元素
<!doctype html>
<html ng-app="a2_10">
<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:400px;
margin: 0px;
padding: 0px
}
ul li {
f?loat: left;
padding: 5px 0px;
}
ul li span {
width: 50px;
f?loat: left;
padding: 0px 10px;
}
</style>
</head>
<body>
<div ng-controller="c2_10">
<ul>
<li>
<span>序号</span>
<span>姓名</span>
<span>性别</span>
<span>是否首条</span>
<span>是否尾条</span>
</li>
<li ng-repeat=" stu in data">
<span>{{$index+1}}</span>
<span>{{stu.name}}</span>
<span>{{stu.sex}}</span>
<span>{{$f?irst?'是':'否'}}</span>
<span>{{$last?'是':'否'}}</span>
</li>
</ul>
</div>
<script type="text/javascript">
var a2_10 = angular.module('a2_10', []);
a2_10.controller('c2_10', ['$scope', function ($scope) {
$scope.data = [
{ name: "张明明", sex: "女" },
{ name: "李清思", sex: "女" },
{ name: "刘小华", sex: "男"},
{ name: "陈忠忠", sex: "男" }
];
}]);
</script>
</body>
</html>
(3)页面效果
执行HTML文件2-10.html,最终实现的页面效果如图2-10所示。
(4)源码分析
在本示例的源码中,首先,在对应页面的控制器代码中,以$scope属性的方式添加了一个名为“data”的数组,用作页面中
- 元素,并在该元素中再添加两个
- 元素,第一个用于标题显示,第二个用于绑定“data”数组内容。
在用于绑定“data”数组内容的第二个 - 元素中,调用Angular中的“ng-repeat”指令完成数据与页面元素的绑定。在绑定过程中,Angular先遍历“data”数组,在遍历时复制一份
- 元素,并通过“stu”对象将控制器中的属性和方法添加至该元素中,在遍历完成后便生成了与数组成员数量对应的
- 元素,并且在这些元素中也添加了需要显示的内容和方法,从而最终实现以列表方式显示集合数据的功能。
在通过“ng-repeat”指令复制元素过程中,可以通过表达式的方式直接调用Angular提供的几个专用的变量$f?irst、$middle、$last和$index。由于这些变量均返回布尔值,因此,可以根据返回的布尔值,再借助“?:”运算符转成中文显示的文字内容,实现的过程如本示例中的源码所示。2.3.3 添加元素样式
在Angular中,添加元素的样式也非常简单,概括起来可以通过下列几种方式来进行。
(1)直接绑定值为CSS类别名称的$scope对象属性
这种方式的操作非常简单,先在控制器中添加一个值为CSS类别名称的属性,然后在页面元素的class或ng-class属性值中,通过双花括号方式绑定属性名即可,如以下代码。$scope.red="red";
上述代码表示在控制器中添加了一个名为“red”的属性,它的属性值是名为“red”的CSS类别名。在添加完“red”属性后,在页面中可以通过下列代码进行调用。
<div ng-class="{{red}}"></div>
等价于下列代码:
<div class="{{red}}"></div>
这种方式操作起来虽然简单,但在控制器中定义CSS类别名称,并不是Angular所提倡的,我们在开发Angular应用时,尽量保证控制器的代码都是处理业务逻辑,并不涉及页面元素。
(2)以字符串数组方式选择性添加CSS类别名称
这种方式将根据控制器中一个布尔类型的属性值来决定页面中元素添加的CSS样式名,当该属性值为true时,添加一个CSS样式名,当属性值为false值时,添加另外一个CSS样式名。下列代码添加一个名为“blnfocus”属性,由它决定页面中元素的样式。$scope.blnfocus=true;
接下来在页面的
元素中添加ng-class属性,并在属性值中通过字符串数组方式来添加CSS类别名称,代码如下。<div ng-class="{true:'red',false:’green’}[blnfocus]"></div>
在上述代码中,
的CSS样式取决于“blnfocus”属性值,当该值为true时,添加“red”样式名,当该值为false时,添加“green”样式名。这种方式只能在两种样式中选择一种,并且{}和[]顺序不可颠倒。在{}中设置可选择的两种样式名称,在[]中放置控制样式的属性名。
(3)通过定义key/value对象的方式来添加多个CSS类别名称
与前面介绍的两种添加CSS类别名的方法相比,第三种方法的功能要强大很多,它可以根据控制显示样式的属性值添加多个样式名。例如,先添加两个用于控制样式显示的“a”和“b”属性,这两个属性的类型均为布尔型,代码如下。$scope.a=false; $scope.b=true;
接下来在页面的
元素中,添加ng-class属性。在设置属性值时,通过定义key/value对象的方式来添加多个CSS样式名,代码如下。<div ng-class="{'red':a ,'green':b}"></div>
在上述ng-class属性值设置过程中,样式名“red”和“green”分别为“key”值,属性值“a”和“b”分别为对应的“value”值。当“value”属性值为true时,则添加对应的“key”即CSS样式名。因此,这种方式可以实现添加多种CSS样式名称,适合在处理复杂样式时使用。
此外,在Angular中,还有另外两个用于添加样式的页面指令,分别为“ng-class-odd”和“ng-class-even”,这两个样式指令是专用于以列表方式显示数据,对应奇数行与偶数行的样式。
接下来,通过一个完整的示例来详细介绍样式在页面中的使用。
示例2-11 添加元素样式
(1)功能描述
在示例2-10的基础之上,在样式方面增加3个功能。首先,将第一个 - 元素中显示的字体加粗;其次,添加“ng-class-odd”和“ng-class-even”两个指令,实现列表的隔行变色的功能;最后,当单击某行
- 的元素时,显示相应的背景色。
(2)实现代码
新建一个HTML文件2-11.html,加入如代码清单2-11所示的代码。
代码清单2-11 添加元素样式<!doctype html> <html ng-app="a2_11"> <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="c2_11"> <ul> <li ng-class="{{bold}}"> <span>序号</span> <span>姓名</span> <span>性别</span> <span>是否首条</span> <span>是否尾条</span> </li> <li ng-class-odd="'odd'" ng-class-even="'even'" ng-repeat=" stu in data" ng-click='li_click($index)' ng-class='{focus: $index==focus}'> <span>{{$index+1}}</span> <span>{{stu.name}}</span> <span>{{stu.sex}}</span> <span>{{$f?irst?'是':'否'}}</span> <span>{{$last?'是':'否'}}</span> </li> </ul> </div> <script type="text/javascript"> var a2_11 = angular.module('a2_11', []); a2_11.controller('c2_11', ['$scope', function ($scope) { $scope.bold = "bold"; $scope.li_click = function (i) { $scope.focus = i; }; $scope.data = [ { name: "张明明", sex: "女" }, { name: "李清思", sex: "女" }, { name: "刘小华", sex: "男" }, { name: "陈忠忠", sex: "男" } ]; }]); </script> </body> </html>
(3)页面效果
执行HTML文件2-11.html,最终实现的页面效果如图2-11所示。
(4)源码分析
在本示例的源代码中,首次定义了名称为“odd”、“even”、“bold”和“focus”的4个样式,分别用于隔行时的两种字体色、标题栏字体变粗和单击某行时的背景色。
其次,在示例的控制器代码中,除添加“data”数组集合外,再添加了一个“bold”属性,用于指定加粗显示字体时的样式名。另外,还添加了一个带参数的“li_click”方法,当调用该方法时,将“focus”属性值设为传入参数值。
再有,在示例的页面代码中,先通过双花括号方式将第一个 - 元素的“ng-class”值与“bold”属性值绑定,由于该值指定的是一个加粗时的样式名,因此,在绑定后,
- 元素中的字体变粗;然后,使用“ng-class-odd”和“ng-class-even”样式指令分别绑定奇数和偶数行的样式名,实现隔行换色的功能;最后,在
- 元素的单击事件中,将执行$scope对象中添加的“li_click()”方法,在该方法中将“$index”(行号值)作为实参传给方法,并且将“focus”属性值设置为“$index”值。因此,当单击某行
- 元素时,“focus”属性值将变为相应的“$index”值。
最后,在示例页面 - 元素的“ng-class”样式指令值中通过key/value对象的方式指定该元素需要添加的样式。由于单击
- 元素时,“$index”变量值和“focus”属性值相同,也就是说,表达式“$index==focus”的返回值为true。因此,“ng-class”样式指令值变为“focus”,最终实现当单击
- 元素时,添加背景样式的页面效果。
2.3.4 控制元素的隐藏与显示状态
在Angular中,可以通过“ng-show”“ng-hide”和“ng-switch”指令来控制元素隐藏与显示的状态,前两个指令直接控制元素的显示和隐藏状态,当“ng-show”值为true或“ng-hide”值为false时,元素显示,反之,元素隐藏。
后一个“ng-switch”指令的功能是显示匹配成功的元素,该指令需要结合“ng-switch-when”和“ng-switch-defalut”指令使用。在“ng-switch”指令中,当指定的“on”值与某个或多个添加“ng-switch-when”指令的元素匹配时,这些元素显示,其他未匹配的元素则隐藏。如果没有找到与“on”值相匹配的元素时,则显示添加了“ng-switch-defalut”指令的元素。
接下来,通过一个示例来演示控制元素隐藏或显示状态的过程。
示例2-12 控制元素的隐藏与显示状态
(1)功能描述
在页面中,调用“ng-show”“ng-hide”和“ng-switch”指令绑定$scope对象的属性值,控制和 - 元素显示或隐藏的状态。
(2)实现代码
新建一个HTML文件2-12.html,加入如代码清单2-12所示的代码。
代码清单2-12 控制元素的隐藏与显示状态<!doctype html> <html ng-app="a2_12"> <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; margin: 0px; padding: 0px } div { margin: 8px 0px; } </style> </head> <body> <div ng-controller="c2_12"> <div ng-show={{isShow}}>陶国荣</div> <div ng-hide={{isHide}}>tao_guo_rong@163.com</div> <ul ng-switch on={{switch}}> <li ng-switch-when="1">陶国荣</li> <li ng-switch-when="2">tao_guo_rong@163.com</li> <li ng-switch-default>更多...</li> </ul> </div> <script type="text/javascript"> var a2_12 = angular.module('a2_12', []); a2_12.controller('c2_12', ['$scope', function ($scope) { $scope.isShow = true; $scope.isHide = false; $scope.switch = 3; }]); </script> </body> </html>
(3)页面效果
执行HTML文件2-12.html,最终实现的页面效果如图2-12所示。
(4)源码分析
在本示例的源代码中,前两个元素分别添加了“ng-show”和“ng-hide”,并通过双花括号绑定了“isShow”属性和“isHide”属性,这两个属性在控制器中添加时的值分别为true和false,因此,这两个元素都将显示在页面中。
此外,在添加“ng-switch”指令的- 元素中,由于“on”值绑定了“switch”属性,而该属性在控制器中添加时的值为3,并且在页面中添加了“ng-switch-when”指令的
- 元素中,没有找到“ng-switch-when”指令值为3的元素,因此,只能显示添加了“ng-switch-default”指令的
- 元素,即最后一行显示内容为“更多…”的
- 元素,最终显示效果如图2-12所示。