指令是所有AngularJS应用最重要的部分。尽管AngularJS已经提供了非常丰富的指令,但还是经常需要创建应用特定的指令。这篇文章会为你讲述如何自定义指令,创建装饰型指令以及组件式指令来扩展html标签.深入指令的所有用法,彻底领会angular指令的魅力。
1.angular中的指令
1.1 创建指令
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
- scope:当前作用域
- element:jq对象
- 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.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); } } });
|