带你走近AngularJS - 体验指令实例
之前我们已经介绍了所有的AngularJS 基础知识,下面让我们通过实例来加深记忆,体验自定义指令的乐趣。
带你走近AngularJS系列:
- 带你走近AngularJS - 基本功能介绍 http://www.linuxidc.com/Linux/2014-05/102140.htm
- 带你走近AngularJS - 体验指令实例 http://www.linuxidc.com/Linux/2014-05/102141.htm
- 带你走近AngularJS - 创建自定义指令 http://www.linuxidc.com/Linux/2014-05/102142.htm
手风琴指令
我们展示的第一个例子是手风琴效果指令:
效果图如下:
在线实例地址:手风琴指令
不使用AngularJS的纯HTML源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | < div class = "accordion" id = "accordion2" >
< div class = "accordion-group" >
< div class = "accordion-heading" >
< a class = "accordion-toggle" data-toggle = "collapse"
data-parent = "#accordion2" href = "#collapseOne" >
Collapsible Group Item #1
</ a >
</ div >
< div id = "collapseOne" class = "accordion-body collapse in" >
< div class = "accordion-inner" >
Anim pariatur cliche...
</ div >
</ div >
</ div >
< div class = "accordion-group" >
< div class = "accordion-heading" >
< a class = "accordion-toggle" data-toggle = "collapse"
data-parent = "#accordion2" href = "#collapseTwo" >
Collapsible Group Item #2
</ a >
</ div >
< div id = "collapseTwo" class = "accordion-body collapse" >
< div class = "accordion-inner" >
Anim pariatur cliche...
</ div >
</ div >
</ div > </ div > |
以上纯 HTML源码也可以实现手风琴效果,但是它仅仅是一些标记,包含了大量的链接和id,不利于维护。
使用AngularJS自定义指令结合以下HTML源码同样可以得到预期效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <body ng-app= "btst" >
<h3>BootStrap手风琴指令</h3>
<btst-accordion>
<btst-pane title= "<b>基本功能</b>" category= "{name:'test'}" >
<div>AngularJS......</div>
</btst-pane>
<btst-pane title= "<b>创建自定义指令</b>" >
<div>使用过 AngularJS ......</div>
</btst-pane>
<btst-pane title= "<b>体验实例</b>" >
<div>之前我们已经介绍了所有的AngularJS......</div>
</btst-pane>
</btst-accordion> </body> |
这一版使用的HTML标记更少,看起来清晰且易维护。
下面,让我们看下指令写法。
首先,我们定义模块"btstAccordion" 指令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | var btst = angular.module( "btst" , []); btst.directive( "btstAccordion" , function () {
return {
restrict: "E" ,
transclude: true ,
replace: true ,
scope: {},
template:
"<div class='accordion' ng-transclude></div>" ,
link: function (scope, element, attrs) {
// 确保 accordion拥有id
var id = element.attr( "id" );
if (!id) {
id = "btst-acc" + scope.$id;
element.attr( "id" , id);
}
// set data-parent and href attributes on accordion-toggle elements
var arr = element.find( ".accordion-toggle" );
for ( var i = 0; i < arr.length; i++) {
$(arr[i]).attr( "data-parent" , "#" + id);
$(arr[i]).attr( "href" , "#" + id + "collapse" + i);
}
// set collapse attribute on accordion-body elements
// and expand the first pane to start
arr = element.find( ".accordion-body" );
$(arr[0]).addClass( "in" ); // expand first pane
for ( var i = 0; i < arr.length; i++) {
$(arr[i]).attr( "id" , id + "collapse" + i);
}
},
controller: function () {}
}; }); |
由于拥有内部HTML内容,所以设置指令的transclude 属性为true。模板使用ng-transclude 指令来声明对应的显示内容。由于模板中只有一个元素,所以没有设置其他选项。
代码中最有趣的部分是link 方法。它在参数element具有id时启作用,如果没有,会依据指令的 Scope自动创建ID。一旦元素拥有了ID值,方法将通过jQuery来选择具有"accordion-toggle"类的子元素并且设置它的 "data-parent" 和 "href" 属性。最后,通过寻找“accordion-body” 元素,并且设置"collapse" 属性。
指令同时声明了一个拥有空方法的controller 。声明controller 是必要的,因为Accordion会包含子元素,子元素将检测父元素的类型和controller 。
下一步需要定义手风琴选项卡的指令。
这一步比较容易,大多数操作将在这个模板中发生,但是它仅仅需要少量的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | btst.directive( 'btstPane' , function () {
return {
require: "^btstAccordion" ,
restrict: "E" ,
transclude: true ,
replace: true ,
scope: {
title: "@"
},
template:
"<div class='accordion-group'>" +
" <div class='accordion-heading'>" +
" <a class='accordion-toggle' data-toggle='collapse'>{{title}}</a>" +
" </div>" +
"<div class='accordion-body collapse'>" +
" <div class='accordion-inner' ng-transclude></div>" +
" </div>" +
"</div>" ,
link: function (scope, element, attrs) {
scope.$watch( "title" , function () {
// NOTE: this requires jQuery (jQLite won't do html)
var hdr = element.find( ".accordion-toggle" );
hdr.html(scope.title);
});
}
}; }); |
require 属性值为"btstPane" ,所以该指令必须用于指令"btstAccordion"中。transclude 属性为true表明选项卡包含HTML标签。scope 下的 "title" 属性将会被实例所替代。
这个例子中的模板比较复杂。注意我们通过ng-transclude 指令来标记元素接收文本内容。
模板中"{{title}}" 属性将会显示标签名称。目前我们仅仅实现了纯文本显示,没有定义其样式。我们使用link 方法可以替换标题为HTML源码从而得到更丰富的样式。
就这样,我们完成了第一个具有实用价值的指令。它功能并不复杂但是足以展示一些AngularJS的重要知识点和技术细节:如何定义嵌套指令,如何生成唯一的元素ID,如何使用jQuery操作DOM以及如何使用$watch 方法监听scope变量的变化。
Google Maps 指令
下一个例子是创建Google地图的指令: