angular.module('modulename')
.directive('myDirective', function(){
return {
restrict: 'EA', //E表示element, A表示attribute,C表示class,M表示commnent,即注释
scope:{
title: '@' //@读属性值,=双向绑定,&用户函数
}
template: '<div>{{myVal}}</div>',
templateUrl: 'app/sample.html',
controller: 'myController',
link:function($scope, element, attrs){}//DOM操作
};
})
return{
//通过设置项来定义
};

})其中return返回的对象包含很多参数,下面一一说明

你知道用AngularJs怎么定义指令吗?

1.restrict

(字符串)可选参数,指明指令在DOM里面以什么形式被声明;

取值有:E(元素),A(属性),C(类),M(注释),其中默认值为A;

E(元素):<directiveName></directiveName>
A(属性):<div directiveName='expression'></div>
C(类): <div class='directiveName'></div>
M(注释):<--directive:directiveName expression-->

2.priority

(数字),可选参数,指明指令的优先级,若在单个DOM上有多个指令,则优先级高的先执行;

设置指令的优先级算是不常用的

比较特殊的的例子是,angularjs内置指令的ng-repeat的优先级为1000,ng-init的优先级为450;

3.terminal

(布尔型),可选参数,可以被设置为true或false,若设置为true,则优先级低于此指令的其他指令则无效,不会被调用(优先级相同的还是会执行)

4.template(字符串或者函数)可选参数,可以是:

(1)一段HTML文本

angular.module("app",[]).directive("hello",function(){

            return{
restrict:'EA',
template:"<div><h3>hello world</h3></div>"
};
})

HTML代码为:<hello></hello>
结果渲染后的HTML为:<hello>
<div><h3>hello world</h3></div>
</hello>
(2)一个函数,可接受两个参数tElement和tAttrs

其中tElement是指使用此指令的元素,而tAttrs则实例的属性,它是一个由元素上所有的属性组成的集合(对象)形如:

{
title:‘aaaa’,
name:'leifeng'
}
下面让我们看看template是一个函数时候的情况

angular.module("app",[]).directive("directitle",function(){

            return{
restrict:'EAC',
template: function(tElement,tAttrs){
var _html = '';
_html += '<div>'+tAttrs.title+'</div>';
return _html;
}
};
})

HTML代码:<directitle title='biaoti'></directitle>
渲染之后的HTML:<div>biaoti</div>
因为一段HTML文本,阅读跟维护起来都是很麻烦的,所用通常会使用templateUrl这个。

5.templateUrl(字符串或者函数),可选参数,可以是

(1)一个代表HTML文件路径的字符串

(2)一个函数,可接受两个参数tElement和tAttrs(大致同上)

注意:在本地开发时候,需要运行一个服务器,不然使用templateUrl会报错 Cross Origin Request Script(CORS)错误

由于加载html模板是通过异步加载的,若加载大量的模板会拖慢网站的速度,这里有个技巧,就是先缓存模板

你可以再你的index页面加载好的,将下列代码作为你页面的一部分包含在里面。

<script type='text/ng-template' id='woshimuban.html'>

<div>我是模板内容</div>

</script>这里的id属性就是被设置在templateUrl上用的。

另一种办法缓存是:

angular.module("template.html", []).run(["$templateCache", function($templateCache) {$templateCache.put("template.html",

"<div>wo shi mu ban</div>");

}]);

6.scope

可选参数,(布尔值或者对象)默认值为false,可能取值:

(1)默认值false。

表示继承父作用域;

(2)true

表示继承父作用域,并创建自己的作用域(子作用域);

(3){}

表示创建一个全新的隔离作用域;

接下来我们通过一个简单明了的例子来说明scope取值不同的差别

<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/ang...
</head>
<body>

<div ng-controller='MainController'>

    父亲: {{name}}
<input ng-model="name" />
<div my-directive></div>

</div>

<script>

 1 angular.module('myApp', [])
2 .controller('MainController', function ($scope) {
3 $scope.name = 'leifeng';
4 })
5 .directive('myDirective', function () {
6 return {
7 restrict: 'EA',
8 scope:false,//改变此处的取值,看看有什么不同
9 template: '<div>儿子:{{ name }}<input ng-model="name"/></div>'
10 };
11 });

依次设置scope的值false,true,{},结果发现(大家别偷懒,动手试试哈)

. 当为false时候,儿子继承父亲的值,改变父亲的值,儿子的值也随之变化,反之亦如此。(继承不隔离)

. 当为true时候,儿子继承父亲的值,改变父亲的值,儿子的值随之变化,但是改变儿子的值,父亲的值不变。(继承隔离)

. 当为{}时候,没有继承父亲的值,所以儿子的值为空,改变任何一方的值均不能影响另一方的值。(不继承隔离)

tip:当你想要创建一个可重用的组件时隔离作用域是一个很好的选择,通过隔离作用域我们确保指令是‘独立’的,并可以轻松地插入到任何HTML app中,并且这种做法防止了父作用域被污染;

6.2隔离作用域可以通过绑定策略来访问父作用域的属性。

 1 <!doctype html>
2 <html ng-app="myApp">
3 <head>
4 <script src="http://cdn.staticfile.org/ang...
5 </head>
6 <body>
7
8 <div ng-controller='MainController'>
9
10 <input type="text" ng-model="color" placeholder="Enter a color"/> //这里输入的color不会被检测到指令中
11 <hello-world></hello-world>
12 </div>
13
14 <script>
15
16 var app = angular.module('myApp',[]);
17 app.controller('MainController',function(){});
18 app.directive('helloWorld',function(){
19 return {
20 scope: {},
21 restrict: 'AE',
22 replace: true,
23 template: '<p style="">>Hello World</p>'
24 }
25 });
26 </script>
27
28 </body>
29 </html>

在输入框改变color的值不会反映到指令中去。

原因在于,这里我们将scope设置为{},产生了隔离作用域。

所以在template模板中{{color}}变成了依赖于自己的作用域,而不是依赖于父作用域。

因此我们需要一些办法来让隔离作用域能读取父作用域的属性,就是绑定策略。

下面我们就来探索设置这种绑定的几种方法

方法一:使用@(@attr)来进行单向文本(字符串)绑定

 1 <!doctype html>
2 <html ng-app="myApp">
3 <head>
4 <script src="http://cdn.staticfile.org/ang...
5 </head>
6 <body>
7
8 <div ng-controller='MainController'>
9
10 <input type="text" ng-model="color" placeholder="Enter a color"/>
11 <hello-world color-attr='{{color}}'></hello-world> //注意这里设置了color-attr属性,绑定了{{color}}
12 </div>
13
14 <script>
15
16 var app = angular.module('myApp',[]);
17 app.controller('MainController',function(){});
18 app.directive('helloWorld',function(){
19 return {
20 scope: {color:'@colorAttr'}, //指明了隔离作用域中的属性color应该绑定到属性colorAttr
21 restrict: 'AE',
22 replace: true,
23 template: '<p style="">>Hello World</p>'
24 }
25 });
26 </script>
27
28 </body>
29 </html>

这种办法只能单向,通过在运行的指令的那个html标签上设置color-attr属性,并且采用{{}}绑定某个模型值。

注意,你也可以再这里直接绑定字符串的颜色值,如:color-attr=“red”;但颜色就是固定值了。

当表达式的值发生变化时,属性color-attr也会发生变化,所以也改变了隔离作用域中的属性color。

tips:如果绑定的隔离作用域属性名与元素的属性名相同,则可以采取缺省写法。

 1 html:<hello-world color="{{color}}"/>
2
3 js定义指令的片段:app.directive('helloWorld',function(){
4
5 return {
6 scope: {
7 color: '@'
8 },
9 ...
10 //配置的余下部分
11 }
12 });

方法二:使用=(=attr)进行双向绑定

 1 <div ng-controller='MainController'>
2
3 <input type="text" ng-model="color" placeholder="Enter a color"/>
4 {{color}}
5 <hello-world color='color'></hello-world> //注意这里的写法
6 </div>
7
8 <script>
9
10 var app = angular.module('myApp',[]);
11 app.controller('MainController',function(){});
12 app.directive('helloWorld',function(){
13 return {
14 scope:{color:'='},
15 restrict: 'AE',
16 replace: true,
17 template: '<div style="Hello World<div><input type="text" ng-model="color"></div></div>'
18 }
19 });
20 </script>

这样一个双向绑定被建立了,改变任何一个input都会改变另一个值。

方法三:使用&来调用父作用域中的函数

 1 <div ng-controller='MainController'>
2
3 <input type="text" ng-model="name" placeholder="Enter a color"/>
4 {{name}}
5 <hello-world saysomething999="say();" name="liucunjie"></hello-world> //注意这里
6 </div>
7
8 <script>
9
10 var app = angular.module('myApp',[]);
11 app.controller('MainController',function($scope){
12 $scope.say = function(){
13 alert('hello');
14 }
15 $scope.name = 'leifeng';
16 });
17 app.directive('helloWorld',function(){
18 return {
19 scope:{
20 saysomething:'&saysomething999',
21 name:'@'
22 },
23 restrict: 'AE',
24 replace: true, //这里设置为true表示什么(单项绑定:....)
25 template: '<button type="button" ng-bind="name" ng-init="saysomething();"></button>'
26 }
27 });
28 </script>

运行之后,弹出alert框。

7.transclude

(布尔值或者字符‘element’),默认值为false;

这个配置选项可以让我们提取包含在指令那个元素里面的内容,再将它放置在指令模板的特定位置

当你开启transclude后,你就可以使用ng-transclude来指明了应该在什么地方放置transcluded内容.

 1 <div ng-controller='MainController'>
2
3 <div class='a'>
4 <p>china</p>
5 <hello-world>
6 {{name}}
7 </hello-world>
8 </div>
9 </div>
10
11 <script>
12
13 var app = angular.module('myApp',[]);
14 app.controller('MainController',function($scope){
15 $scope.name = 'leifeng';
16 });
17 app.directive('helloWorld',function(){
18 return {
19 scope:{},
20 restrict: 'AE',
21 transclude: true,
22 template: '<div class="b"><div ng-transclude>你看不见我</div></div>'
23 }
24 });
25 </script>

另外当开启transclude,会创建一个新的transclude空间,并且继承了父作用域(即使Scope设置为隔离作用域),

上面代码中的{{name}}是依赖于父作用域的,仍然能被渲染出来,就说明了这点。

我们再看看生成的html为下图所示,可以发现文本“你看不见我”消失了,这是因为被transclude内容替换掉了。

8.controller

可以是一个字符串或者函数。

若是为字符串,则将字符串当做是控制器的名字,来查找注册在应用中的控制器的构造函数

 1 angular.module('myApp', [])
2 .directive('myDirective', function() {
3 restrict: 'A', // 始终需要
4 controller: 'SomeController'
5 })
6 // 应用中其他的地方,可以是同一个文件或被index.html包含的另一个文件
7 angular.module('myApp')
8 .controller('SomeController', function($scope, $element, $attrs, $transclude) {
9 // 控制器逻辑放在这里
10 });
11 也可以直接在指令内部的定义为匿名函数,同样我们可以再这里注入任何服务($log,$timeout等等)
12
13 angular.module('myApp',[])
14 .directive('myDirective', function() {
15 restrict: 'A',
16 controller:
17 function($scope, $element, $attrs, $transclude) {
18 // 控制器逻辑放在这里
19 }
20 });

另外还有一些特殊的服务(参数)可以注入

(1)$scope,与指令元素相关联的作用域

(2)$element,当前指令对应的 元素

(3)$attrs,由当前元素的属性组成的对象

(4)$transclude,嵌入链接函数,实际被执行用来克隆元素和操作DOM的函数

注意: 除非是用来定义一些可复用的行为,一般不推荐在这使用。

<my-site site="http://www.cnblogs.com/yoissee"><div>coder——231的博客</div></my-site>
 1 angular.module('myApp',[]).directive('mySite', function () {
2 return {
3 restrict: 'EA',
4 transclude: true, //注意此处必须设置为true
5 controller:
6 function ($scope, $element,$attrs,$transclude,$log) { //在这里你可以注入你想注入的服务
7 $transclude(function (clone) {
8 var a = angular.element('<a>');
9 a.attr('href', $attrs.site);
10 a.text(clone.text()); //这里的clone.text()就是 coder_231的博客
11 $element.append(a);
12 });
13 $log.info("hello everyone");
14 }
15 };

注意:使用$transclude会生成一个新的作用域。

默认情况下,如果我们简单实用$transclude(),那么默认的其作用域就是$transclude生成的作用域

但是如果我们实用$transclude($scope,function(clone){}),那么作用域就是directive的作用域了

那么问题又来了。如果我们想实用父作用域呢

可以使用$scope.$parent

 1 <div ng-controller='parentctrl'>
2
3 <div ng-controller='sonctrl'>
4 <my-site site="http://www.cnblogs.com/cunjieliu"><div>coder的博客</div></my-site>
5 </div>
6 </div> <script>
7
8 var app = angular.module('myApp',[]);
9 app.controller('sonctrl',function($scope){
10 $scope.title = 'hello son';
11 });
12 app.controller('parentctrl',function($scope){
13 $scope.title = 'hello parent';
14 });
15 app.directive('mySite', function () {
16 return {
17 restrict: 'EA',
18 transclude: true,
19 controller:
20 function ($scope, $element,$attrs,$transclude,$log) {
21 var a = $transclude();
22 $element.append(a);
23 $log.info($scope.title); //‘hello son'
24 $log.info($scope.$parent.title); //hello parent
25 }
26 };
27 });
28 </script>

9.controllerAs

这个选项的作用是可以设置你的控制器的别名

一般以前我们经常用这样方式来写代码:

1 angular.module("app",[]) .controller("demoController",["$scope",function($scope){
2
3 $scope.title = "angualr";
4 }])
5
6 <div ng-app="app" ng-controller="demoController">
7
8 {{title}}
9 </div>

后来angularjs1.2给我们带来新语法糖,所以我们可以这样写

1 angular.module("app",[]) .controller("demoController",[function(){
2
3 this.title = "angualr";
4 }])
5
6 <div ng-app="app" ng-controller="demoController as demo">
7
8 {{demo.title}}
9 </div>

10.require(字符串或者数组)

字符串代表另一个指令的名字,它将会作为link函数的第四个参数

具体用法我们可以举个例子说明

假设现在我们要编写两个指令,两个指令中的link链接函数中(link函数后面会讲)存在有很多重合的方法,

这时候我们就可以将这些重复的方法写在第三个指令的controller中(上面也讲到controller经常用来提供指令间的复用行为

然后在这两个指令中,require这个拥有controller字段的的指令(第三个指令),

最后通过link链接函数的第四个参数就可以引用这些重合的方法了。

 1 <outer-directive>
2
3 <inner-directive></inner-directive>
4 <inner-directive2></inner-directive2>
5 </outer-directive>
6 <script>
7 var app = angular.module('myApp', []);
8 app.directive('outerDirective', function() {
9 return {
10 scope: {},
11 restrict: 'AE',
12 controller: function($scope) {
13 this.say = function(someDirective) {
14 console.log('Got:' + someDirective.message);
15 };
16 }
17 };
18 });
19 app.directive('innerDirective', function() {
20 return {
21 scope: {},
22 restrict: 'AE',
23 require: '^outerDirective',
24 link: function(scope, elem, attrs, controllerInstance) {
25 scope.message = "Hi,leifeng";
26 controllerInstance.say(scope); //打印hi.leifeng
27 }
28 };
29 });
30 app.directive('innerDirective2', function() {
31 return {
32 scope: {},
33 restrict: 'AE',
34 require: '^outerDirective',
35 link: function(scope, elem, attrs, controllerInstance) { //第4个参数指向的就是那个controller
36 scope.message = "Hi,shushu";
37 controllerInstance.say(scope);
38 }
39 };
40 });
41
42 </script>

上面例子中的指令innerDirective和指令innerDirective2复用了定义在指令outerDirective的controller中的方法

也进一步说明了,指令中的controller是用来让不同指令间通信用的。

另外我们可以在require的参数值加上下面的某个前缀,这会改变查找控制器的行为:

(1)没有前缀,指令会在自身提供的控制器中进行查找,如果找不到任何控制器,则会抛出一个error

(2)?如果在当前的指令没有找到所需的控制器,则会将null传给link连接函数的第四个参数

(3)^如果在当前的指令没有找到所需的控制器,则会查找父元素的控制器

(4)?^组合

11.Anguar的指令编译过程

首先加载angularjs库,查找到ng-app指令,从而找到应用的边界,根据ng-app划定的作用域来调用$compile服务进行编译,angularjs会遍历整个HTML文档,并根据js中指令

的定义来处理在页面上声明的各个指令按照指令的优先级(priority)排列,根据指令中的配置参数(template,place,transclude等)转换DOM,然后就开始按顺序执行各指令的

compile函数(如果指令上有定义compile函数)对模板自身进行转换。

注意:此处的compile函数是我们指令中配置的,跟上面说的$compile服务不一样。

每个compile函数执行完后都会返回一个link函数,所有的link函数会合成一个大的link函数然后这个大的link函数就会被执行,主要做数据绑定,通过在DOM上注册监听器来动态

修改scope中的数据,或者是使用$watchs监听 scope中的变量来修改DOM,从而建立双向绑定等等。若我们的指令中没有配置compile函数,那我们配置的link函数就会运行,

她做的事情大致跟上面complie返回之后所有的link函数合成的的大的link函数差不多。

所以:在指令中compile与link选项是互斥的,如果同时设置了这两个选项,那么就会把compile所返回的函数当做是链接函数,而link选项本身就会被忽略掉。

AngularJS 指令(意义)的更多相关文章

  1. 【转】angularjs指令中的compile与link函数详解

    这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下   通常大家在 ...

  2. angularjs指令中的compile与link函数详解

    这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下   通常大家在 ...

  3. AngularJS指令

    1. AngularJS指令的特点: AngularJS通过被称为指令的新属性来扩展HTML,指令的前缀为ng-. AngularJS通过内置的指令来为应用添加功能. AngularJS允许你自定义指 ...

  4. angularjs指令参数transclude

    angularjs指令参数transclude transclude翻译为嵌入,和之前看到的vue中的slots作用差不多,目的是将指令元素的子内容嵌入到指令的模板中 定义指令 <div sid ...

  5. angularjs 指令—— 绑定策略(@、=、&)

    angularjs 指令—— 绑定策略(@.=.&) 引入主题背景:angular 的指令配置中的template可以直接使用硬编码写相应的代码,不过也可以根据变量,进行动态更新.那么需要用到 ...

  6. AngularJS 指令

    AngularJS 指令 AngularJS 指令是扩展的 HTML 属性,带有前缀 ng-. ng-app 指令 ng-app 指令定义了 AngularJS 应用程序的 根元素. ng-app 指 ...

  7. angularjs指令(二)

    最近学习了下angularjs指令的相关知识,也参考了前人的一些文章,在此总结下. 欢迎批评指出错误的地方.   Angularjs指令定义的API AngularJs的指令定义大致如下 angula ...

  8. angularJs指令执行的机制==大概的三个阶段

    第一阶段:加载阶段 angularJs要运行的话,需要去等待angular.js加载完成,加载完之后呢,angular就会去查找到ng-app这个指令,ng-app在每个应用里面只能出现一次, 它也就 ...

  9. AngularJS学习笔记二:AngularJS指令

    AngularJS 指令: AngularJS 通过被称为 指令 的新属性来扩展 HTML. AngularJS 指令是扩展的 HTML 属性,带有前缀 ng-. 几个常用 指令: ng-app 指令 ...

  10. AngularJs指令(一)

    AngularJs应用现在越来越流行了,谷歌都与微软合作支持AngularJS2.0,这是要逆天了,说明AngularJs将来大势所趋.最近想跳槽,又重新拾起了AngluarJs(之前由于缺少项目应用 ...

随机推荐

  1. Broadcasting

    目录 Broadcasting Key idea How to understand? Why broadcasting? Broadcastable? Broadcast VS Tile Broad ...

  2. loadrunner 添加负载机

    1.打开Controller 2. 添加负载 3. 配置参数 4.完成

  3. 集训第六周 数学概念与方法 J题 数论,质因数分解

    Description Tomorrow is contest day, Are you all ready? We have been training for 45 days, and all g ...

  4. POJ 2718 Smallest Difference(贪心 or next_permutation暴力枚举)

    Smallest Difference Description Given a number of distinct decimal digits, you can form one integer ...

  5. 如何实现IIS 7.0对非HTTP协议的支持

    在<再谈IIS与ASP.NET管道>介绍各种版本的IIS的设计时,我们谈到IIS 7.0因引入WAS提供了对非HTTP协议的支持.这个对于WCF的服务寄宿来说意义重大,它意味着我们通过II ...

  6. HDU 1079 简单博弈

    判断下一步能否到达必胜态,如果可以当前状态就是必败态,否则当前状态记为必胜态 #include <cstdio> #include <cstring> #include < ...

  7. 贪吃的九头龙(tyvj P1523)

    T2 .tyvj   P1523贪吃的九头龙 描述 传说中的九头龙是一种特别贪吃的动物.虽然名字叫“九头龙”,但这只是说它出生的时候有九个头,而在成长的过程中,它有时会长出很多的新头,头的总数会远大于 ...

  8. msp430入门编程10

    msp430中C语言操作端口I/O10 msp430中C语言的模块化头文件及实现11 msp430中C语言的模块化头文件及库文件12 msp430入门学习 msp430入门编程

  9. 远程调试 Android 设备使用入门(谷歌翻译版)

    移动前端调试方案(Android + Chrome 实现远程调试) 目录 要求 第 1 步:发现您的 Android 设备 第 2 步:从您的开发计算机调试 Android 设备上的内容. 更多操作: ...

  10. laravel notification

    mail篇 public function via($notifiable) { return ['mail']; } 1.新建notification类 php artisan make:notif ...