Angular指令

指令是所有AngularJS应用最重要的部分。尽管AngularJS已经提供了非常丰富的指令,但还是经常需要创建应用特定的指令。这篇文章会为你讲述如何自定义指令,创建装饰型指令以及组件式指令来扩展html标签.深入指令的所有用法,彻底领会angular指令的魅力。

1.angular中的指令

1.1 创建指令

1
<my-dire></my-dire>
1
2
3
4
5
6
var app = angular.module('appModule',[]);
app.directive('myDire',function () {
return {
}
});

1.2 模板

1
2
3
4
5
6
var app = angular.module('appModule',[]);
app.directive('myDire',function () {
return {
+ template:'<div>Hello</div>'
}
});

1.3 transclude

保留指令中的内容

1
<my-dire>world</my-dire>

1
2
3
4
5
return {
+ transclude:true,
- template:'<div>Hello</div>'
+ template:'<div>Hello <span ng-transclude></span></div>'
}

1.3.1 面板

引入bootstrap

1
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.css">

增加panel.html

1
2
3
4
5
<div class="panel panel-default">
<div class="panel-heading">这是一个面板</div>
<div class="panel-body" ng-transclude>
</div>
</div>

修改指令代码

1
2
3
4
return {
transclude:true,
+ templateUrl:'panel.html',
}

1.4 link函数

link函数是用来链接视图和scope

  1. scope:当前作用域
  2. element:jq对象
  3. attrs:当前指令上的属性
1
2
3
4
5
6
7
return {
transclude:true,
templateUrl:'panel.html',
+ link: function (scope,element,attrs) {
+
+ }
}

1.4.1 给面板增加传入的标题

增加title属性

1
<my-dire title="这是头部">这是一个面板,helloAngular</my-dire>

增加属性值

1
2
3
4
<div class="panel panel-default">
+ <div class="panel-heading">{{title}}</div>
<div class="panel-body" ng-transclude></div>
</div>

声明标题

1
2
3
4
5
return{
link: function (scope,element,attrs) {
+ scope.title = attrs["title"];
}
}

1.5 独立作用域

可以为当前指令设置独立作用域

1
2
3
return {
+ scope:true,
}

1.6 动态引用数据

1.6.1 “@”引用字符串

指令和作用域间的交互
声明控制器

1
2
3
4
5
6
app.controller('appCtrl',function ($scope) {
$scope.title = [
{name:'第一个面板'},
{name:'第二个面板'}
]
});

挂载scope上的属性

1
2
<my-dire title="{{title[0].name}}">这是一个面板,helloAngular</my-dire>
<my-dire title="{{title[1].name}}">这是二个面板,helloAngular</my-dire>

在当前作用域下声明title属性,引用对应的值

1
2
3
4
5
6
7
return {
transclude:true,
templateUrl:'panel.html',
scope:{
title:'@'
}
}

1.6.2 “=”引用scope上的属性

修改html

1
2
<my-dire title="title1">这是一个面板,helloAngular</my-dire>
<my-dire title="title2">这是一个面板,helloAngular</my-dire>

增加动态属性

1
2
3
4
app.controller('appCtrl',function ($scope) {
$scope.title1 = 'hello1';
$scope.title2 = 'hello2'
});

修改指令

1
2
3
scope:{
title:'='
}

1.6.3 “=”与”@”区别

@单向绑定
html页面

1
2
控制器:<input type="text" ng-model="home">
<my-dire home="{{home}}"></my-dire>

控制器

1
2
3
4
5
6
7
8
9
10
11
12
app.controller('appCtrl',function ($scope) {
$scope.home = 'home'
});
app.directive('myDire',function () {
return {
transclude:true,
template:'指令内部<input type="text" ng-model="home">',
scope:{
home:'@'
}
}
});

=双向绑定
html页面

1
控制器:<input type="text" ng-model="hobby">

1
2
3
4
5
6
7
8
9
10
11
app.controller('appCtrl',function ($scope) {
$scope.home = 'home';
+ $scope.hobby = 'hobby';
});
return {
+ template:'指令内部<input type="text" ng-model="hobby">',
scope:{
home:'@',
+ hobby:'='
}
}

1.6.4 &绑定函数

html绑定方法

1
<my-dire home ="home(person)" name="{{name}}"></my-dire>

指令中调用函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.controller('appCtrl',function ($scope) {
$scope.name = 'zfpx';
$scope.home = function (who) {
alert(who);
}
});
app.directive('myDire',function () {
return {
template:'{{name}}<div ng-click="home({person:name})">谁的家</div>',
scope:{
home:'&',name:'@'
}
}
});

1.7 replace替换指令

增加replace:true替换原有指令

1
2
3
return {
replace:true
}

1.8 compile函数

在link函数前执行,编译模板,返回的函数为link函数

1
<my-dire time="3"></my-dire>

指令中增加compile函数

1
2
3
4
5
6
7
8
9
10
11
12
13
return {
transclude:true,
template:'<div>Hello,zfpx {{title}}</div>',
compile: function (element,attrs) {
var tmpl = element.children();
for(var i = 0; i < attrs.time-1;i++){
element.append(tmpl.clone());
}
return function (scope,element,attrs) {
scope.title = '123';
}
},
}

2.指令和指令间的交互

创建多个指令,依赖于girl指令

1
<girl love-money ng-click="show()">Angular MM</girl>

创建指令公有部分

1
2
3
4
5
6
7
8
9
10
11
12
13
app.directive('girl',function () {
return {
controller: function ($scope) {
var arr = [];
this.add = function (attrs) {
arr.push(attrs);
};
$scope.show = function () {
alert(arr);
}
}
}
});

创建指令间的依赖

1
2
3
4
5
6
7
8
app.directive('loveMoney',function () {
return {
require:'^girl',
link: function (scope,element,attrs,girlCtrl) {
girlCtrl.add('loveMoney');
}
}
});

3.opener指令demo

增加css样式

1
2
3
4
5
6
7
8
9
10
11
.title{
width: 100px;
height: 30px;
line-height: 30px;
background: yellow;
}
.content{
width: 100px;
height: 100px;
background: red;
}

增加指令

1
<opener title="标题1">这是内容1</opener>

增加引用模板

1
2
<div class="title" ng-click="show()">{{title}}</div>
<div class="content" ng-show="flag" ng-transclude></div>

增加指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
app.directive('opener',function () {
return {
templateUrl:'open.html',
transclude:true,
scope:{
title:'@'
},
link:function(scope,element,attrs){
scope.flag = true;
scope.show = function () {
scope.flag = !scope.flag;
}
}
}
});

4.opener组

增加组

1
2
3
4
<group>
<opener title="标题1">这是内容1</opener>
<opener title="标题2">这是内容2</opener>
</group>

设置指令

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
app.directive('group', function () {
return {
controller: function ($scope) {
var arr = [];
this.add = function (scope) {
arr.push(scope);
}
this.close = function (scope) {
for(var i = 0; i<arr.length;i++){
if(arr[i]!=scope){
arr[i].flag = false;
}
}
}
}
}
});
app.directive('opener',function () {
return {
templateUrl:'open.html',
transclude:true,
require:'^group',
scope:{
title:'@'
},
link:function(scope,element,attrs,groupCtrl){
scope.flag = false;
scope.show = function () {
scope.flag = !scope.flag;
groupCtrl.close(scope);
};
groupCtrl.add(scope);
}
}
});