AngularJS开发之_指令

指令是什么?    指令是我们用来扩展浏览器能力的技术之一。在DOM编译期间,和HTML关联着的指令会被检测到,并且被执行。这使得指令可以为DOM指定行为,或者改变它。

1.指令的匹配模式

index.html :

 1 <!doctype html>
 2 <html ng-app="MyModule">
 3     <head>
 4         <meta charset="utf-8">
 5     </head>
 6     <body>
 7         <hello></hello>
 8         <div hello></div>
 9         <div class="hello"></div>
10         <!-- directive:hello -->
11         <div></div>
12     </body>
13     <script src="framework/angular-1.3.0.14/angular.js"></script>
14     <script src="HelloAngular_Directive.js"></script>
15 </html>

helloAngular_Directive.js :

1 var myModule = angular.module("MyModule", []);
2 myModule.directive("hello", function() {
3     return {
4         restrict: ‘AEMC‘,
5         template: ‘<div>Hi everyone!</div>‘,
6         replace: true
7     }
8 });

html中包含五个元素,其中一个是注释的元素,JS中定义了一个模块和模块的指令。

OK,不要急,先来看一下 directive 是什么意思,directive的意思是指令,顾名思义,定义一个指令,名字叫 “hello”.

首先,看一下 restrict  ,  restrict的意思是限制,约束。也就是要讲的指令的匹配模式,共有四种:

(1)E: 元素(即html中的<hello></hello>);

(2)A(默认) :属性 (<div hello></div>);

(3)C: 样式类(<div class="hello"></div>)

(4)M: 注释(<!-- directive:hello -->)

常用 A E , 推荐使用这两个。下图就是匹配到的指令元素,并替换了元素的内容,至于怎么替换的内容,继续往下看。

接下来,看一下 template ,template的意思是模板,也就是要替换的内容。但是在js中组织和拼接div这些元素的代码,很费劲的。怎么办呢。有办法,那就是 templateUrl, 把要替换的元素内容写到一个页面里面。嗯如下所示:

1 var myModule = angular.module("MyModule", []);
2 myModule.directive("hello", function() {
3     return {
4         restrict: ‘AECM‘,
5         templateUrl: ‘hello.html‘,
6         replace: true
7     }
8 });


如果我们想要在别的指令中也是用这个hello.html怎么办,那么就有出现了一个缓存的解决办法。看下面的 run 方法在加载完所有模块后,只执行一次,然后把模板缓存起来,当有指令需要调用时,就调用 $templateCache.get().

 1 var myModule = angular.module("MyModule", []);
 2 //注射器加载完所有模块时,此方法执行一次
 3 myModule.run(function($templateCache){
 4     $templateCache.put("hello.html","<div>Hello everyone!!!!!!</div>");
 5 });
 6 myModule.directive("hello", function($templateCache) {
 7     return {
 8         restrict: ‘AECM‘,
 9         template: $templateCache.get("hello.html"),
10         replace: true
11     }
12 });

接下来,再看一下 replace(”替换“),replace:true 会替换元素的内容。但是不想替换内容只是想添加一个内容呢,,没事,,还有 transclude 

1 var myModule = angular.module("MyModule", []);
2 myModule.directive("hello", function() {
3     return {
4         restrict:"AE",
5         transclude:true,
6         template:"<div>Hello everyone!<div ng-transclude></div></div>"
7     }
8 });


最后介绍一下AngularJS的运行机制:

2.指令和控制器的交互。

index.html :

 1 <!doctype html>
 2 <html ng-app="MyModule">
 3     <head>
 4         <meta charset="utf-8">
 5     </head>
 6     <body>
 7         <div ng-controller="MyCtrl">
 8             <loader howToLoad="loadData()">滑动加载</loader>
 9         </div>
10         <div ng-controller="MyCtrl2">
11             <loader howToLoad="loadData2()">滑动加载</loader>
12         </div>
13     </body>
14     <script src="framework/angular-1.3.0.14/angular.js"></script>
15     <script src="Directive&Controller.js"></script>
16 </html>

Directive&Controller.js :

 1 var myModule = angular.module("MyModule", []);
 2 myModule.controller(‘MyCtrl‘, [‘$scope‘, function($scope){
 3     $scope.loadData=function(){
 4         console.log("加载数据中...");
 5     }
 6 }]);
 7 myModule.controller(‘MyCtrl2‘, [‘$scope‘, function($scope){
 8     $scope.loadData2=function(){
 9         console.log("加载数据中...22222");
10     }
11 }]);
12 myModule.directive("loader", function() {
13     return {
14         restrict:"AE",
15         link:function(scope,element,attrs){
16             element.bind(‘mouseenter‘, function(event) {
17                 //(1)scope.loadData();
18                 //(2)scope.$apply("loadData()");
19                 // 注意这里的坑,howToLoad会被转换成小写的howtoload
20                 scope.$apply(attrs.howtoload);
21             });
22         }
23     }
24 });

现在我们想要实现的效果是当鼠标滑过div元素时,调用一个加载数据的方法。

hmtl中我们定义了两个控制器,然后两个控制器中都使用了loader指令,并且,每个指令中都有一个参数 howToLoad .

关于指令中的 link ,上面介绍运行机制是已经看到了,是用来操作dom和绑定监听事件的。link中会有三个参数:scope(指令所属的控制器中的 $scope 对象)、element(指令所属dom元素)、attrs(dom元素所传的参数,如howToLoad 参数给的值 loadData()).

然后对于如何调用所需函数,有两种方法:

(1)scope.loadData() ,这种方法是有局限的,如,MyCtrl1 控制器中的指令所调用的方法是MyCtrl1控制器中所定义的loadData() 方法,但是MyCtrl2就会报错了,因为没有loadData().       所有就有了另个一个方法。

(2)scope.$apply() , $apply()方法会从所有控制器中找到多对应的方法。这就实现了指令的复用。

3.指令间的交互。

index.html :

 1 <!doctype html>
 2 <html ng-app="MyModule">
 3 <head>
 4     <meta charset="utf-8">
 5     <link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
 6     <script src="framework/angular-1.3.0.14/angular.js"></script>
 7     <script src="Directive&Directive.js"></script>
 8 </head>
 9 <body>
10     <div class="row">
11         <div class="col-md-3">
12             <superman strength>动感超人---力量</superman>
13         </div>
14     </div>
15     <div class="row">
16         <div class="col-md-3">
17             <superman strength speed>动感超人2---力量+敏捷</superman>
18         </div>
19     </div>
20     <div class="row">
21         <div class="col-md-3">
22             <superman strength speed light>动感超人3---力量+敏捷+发光</superman>
23         </div>
24     </div>
25 </body>
26 </html>


Directive&Directive.js :

 1 var myModule = angular.module("MyModule", []);
 2 myModule.directive("superman", function() {
 3     return {
 4         scope: {},//独立作用域
 5         restrict: ‘AE‘,
 6         controller: function($scope) {
 7             $scope.abilities = [];
 8             this.addStrength = function() {
 9                 $scope.abilities.push("strength");
10             };
11             this.addSpeed = function() {
12                 $scope.abilities.push("speed");
13             };
14             this.addLight = function() {
15                 $scope.abilities.push("light");
16             };
17         },
18         link: function(scope, element, attrs) {
19             element.addClass(‘btn btn-primary‘);
20             element.bind("mouseenter", function() {
21                 console.log(scope.abilities);
22             });
23         }
24     }
25 });
26 myModule.directive("strength", function() {
27     return {
28         require: ‘^superman‘,
29         link: function(scope, element, attrs, supermanCtrl) {
30             supermanCtrl.addStrength();
31         }
32     }
33 });
34 myModule.directive("speed", function() {
35     return {
36         require: ‘^superman‘,
37         link: function(scope, element, attrs, supermanCtrl) {
38             supermanCtrl.addSpeed();
39         }
40     }
41 });
42 myModule.directive("light", function() {
43     return {
44         require: ‘^superman‘,
45         link: function(scope, element, attrs, supermanCtrl) {
46             supermanCtrl.addLight();
47         }
48     }
49 });

定义了一个superman的指令和另外三个指令,分别是strength、speed、light、

后面三个指令都有一个 require 参数,是指都依赖superman指令,link中的最后一个参数就是superman指令的引用。

4.scope("作用域") 的绑定策略。

scope的绑定策略有三种:

(1)@ :把当前属性作为字符串传值。还可以绑定来自外层scope的值,在属性值中插入{{}}即可。

(2)= :与父scope中的属性进行双向绑定。

(3)& :传递一个来自父scope的函数,稍后调用。

index.html :

 1 <!doctype html>
 2 <html ng-app="MyModule">
 3     <head>
 4         <meta charset="utf-8">
 5         <link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
 6     </head>
 7     <body>
 8         <div ng-controller="MyCtrl">
 9             <drink flavor="{{ctrlFlavor}}"></drink>
10         </div>
11     </body>
12     <script src="framework/angular-1.3.0.14/angular.js"></script>
13     <script src="ScopeAt.js"></script>
14 </html>

ScopeAt.js :

 1 var myModule = angular.module("MyModule", []);
 2 myModule.controller(‘MyCtrl‘, [‘$scope‘, function($scope){
 3     $scope.ctrlFlavor="百威";
 4 }])
 5 myModule.directive("drink", function() {
 6     return {
 7         restrict:‘AE‘,
 8         scope:{
 9             flavor:‘@‘
10         },
11         template:"<div>{{flavor}}</div>"
12          //,
13          //link:function(scope,element,attrs){
14          //    scope.flavor=attrs.flavor;
15          //}
16     }
17 });

使用link进行指令和控制器两个作用域中数据的绑定。如果用scope中@的话,就不需要link这么麻烦了,angularJS会自动进行绑定。

接下来看scope 的 ”=“ 绑定策略:

1         <div ng-controller="MyCtrl">
2             Ctrl:
3             <br>
4             <input type="text" ng-model="ctrlFlavor">
5             <br>
6             Directive:
7             <br>
8             <drink flavor="ctrlFlavor"></drink>
9         </div>
 1 var myModule = angular.module("MyModule", []);
 2 myModule.controller(‘MyCtrl‘, [‘$scope‘, function($scope){
 3     $scope.ctrlFlavor="百威";
 4 }])
 5 myModule.directive("drink", function() {
 6     return {
 7         restrict:‘AE‘,
 8         scope:{
 9             flavor:‘=‘
10         },
11         template:‘<input type="text" ng-model="flavor"/>‘
12     }
13 });

这个例子中有两个输入框,第一个绑定了MyCtrl控制器中的scope对象的ctrlFlavor 属性。第二个绑定的是指令中的flavor属性。 但是在drink 指令中 scope对象的flavor 属性 用了 ”=“ ,与父scope中的属性进行双向数据绑定。所以两个值有一个改动,另一个属性值也会改动。

最后来看一下 scope 的 ”&“ 绑定策略:

index.html :

1     <body>
2         <div ng-controller="MyCtrl">
3             <greeting greet="sayHello(name)"></greeting>
4             <greeting greet="sayHello(name)"></greeting>
5             <greeting greet="sayHello(name)"></greeting>
6         </div>
7     </body>
 1 var myModule = angular.module("MyModule", []);
 2 myModule.controller(‘MyCtrl‘, [‘$scope‘, function($scope){
 3     $scope.sayHello=function(name){
 4         alert("Hello "+name);
 5     }
 6 }])
 7 myModule.directive("greeting", function() {
 8     return {
 9         restrict:‘AE‘,
10         scope:{
11             greet:‘&‘
12         },
13         template:‘<input type="text" ng-model="userName" /><br/>‘+
14                  ‘<button class="btn btn-default" ng-click="greet({name:userName})">Greeting</button><br/>‘
15     }
16 });

点击按钮 会调用greet()函数,在前面html中已经指定了greet要绑定sayHello()函数,函数的参数来绑定 ng-model 的 输入框。

4.AngularJS内置指令。

不同版本的内置指令数目不同,详细的看官方API(----api----)

http://docs.ngnice.com/api/ng/directive

5.Angular-UI。

Angular-UI (http://angular-ui.github.io/)

复杂的指令终于结束了,Angular-UI封装了很多好的指令可以直接使用。省得自己挨个再写,费劲。关于详细的一些指令的用法,多看看API ,很好学。

希望自己越来越厉害,全能型人才即将诞生。哈哈哈哈!!

多关注博客哦http://xinxingyu.cnblogs.com/

时间: 2024-07-30 17:28:45

AngularJS开发之_指令的相关文章

AngularJS开发最常犯的10个错误

简介 AngularJS是目前最为活跃的Javascript框架之一,AngularJS的目标之一是简化开发过程,这使得AngularJS非常善于构建小型app原型,但AngularJS对于全功能的客户端应用程序同样强大,它结合了开发简便,特性广泛和出众的性能,使其被广泛使用.然而,大量使用也会产生诸多误区.以下这份列表摘取了常见的一些AngularJS的错误用法,尤其是在app开发过程中. 1. MVC目录结构 AngularJS,直白地说,就是一个MVC框架.它的模型并没有像backbone

AngularJS开发人员最常犯的10个错误

AngularJS是目前最为活跃的Javascript框架之一,AngularJS的目标之一是简化开发过程,这使得AngularJS非常善于构建小型app原型,但AngularJS对于全功能的客户端应用程序同样强大,它结合了开发简便,特性广泛和出众的性能,使其被广泛使用.然而,大量使用也会产生诸多误区.以下这份列表摘取了常见的一些AngularJS的错误用法,尤其是在app开发过程中. 1. MVC目录结构 AngularJS,直白地说,就是一个MVC框架.它的模型并没有像backbone.js

AngularJS开发指南7:AngularJS本地化,国际化,以及兼容IE低版本浏览器

AngularJS本地化,国际化 国际化,简写为i18n,指的是使产品快速适应不同语言和文化. 本地化,简称l10n,是指使产品在特定文化和语言市场中可用. 对开发者来说,国际化一个应用意味着将所有的文字和其他因地区而异的数据从应用中抽离出来. 本地化意味着为这些抽离的数据和文字提供翻译和转变成本地的格式. 目前,AngularJS支持日期,数字和货币的国际化和本地化. 另外,AngularJS还通过ngPluralize指令支持本地多元化. 所有的AngularJS本地化组件都依赖于$loca

用angularjs开发下一代web应用(二):angularjs应用骨架(一)

1.调用angularjs 1>加载angularjs库 可以从google的CDN(内容分发网络)中加载,获取快,并且可以在多个应用之间缓存脚本库(建议使用这种方式,但是中国的特殊国情,不能用这种方式): <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script> 本地主机方式. 2>使用ng-app申明angular的边界

用angularjs开发下一代web应用(二):angularjs应用骨架(二)

1.浅谈非入侵式JavaScript <div ng-click="doSomething()">...</div>这些指令和原来的事件处理器有以下不同之处: 在所有浏览器中具有相同的行为.Angular将会帮你屏蔽差异性. 不会在全局命名空间中进行操作.你所指定的表达式只能访问元素控制器作用域范围内的函数和数据. 2.列表.表格以及其他迭代型元素         ng-repeat可能是最有用的Angular指令了,它可以根据集合中的项目一次创建一组元素的多份

用angularjs开发下一代web应用(一):angularjs简介

1.客户端模板 与普通的web方式及ajax方式不同, 在angular中,模板和数据都会发送到浏览器中,然后在客户端进行装配.这样一来,服务器的角色就变成了仅仅为这些模板提供一些静态资源,然后为这些模板提供所需的正确数据.{{ }}:单向的数据绑定 2.MVC 在angular应用中,视图就是DOM({{ }}),控制器就是js类(ng-controller),而模型数据则被存储在对象的属性中($scope:将数据绑定到UI的元素上). 3.数据绑定 仅仅声明UI中的某部分需要映射到某个js属

AngularJs开发——控制器间的通信

AngularJs开发——控制器间的通信 指令与控制器之间通信,无非是以下几种方法: 基于scope继承的方式 基于event传播的方式 service的方式 基于scope继承的方式 最简单的让控制器之间进行通信的方法是通过scope的继承.假设有两个控制器Parent.Child,Child 在 Parent 内,那Child 可以称为控制器Parent的子控制器,它将继承父控制器Parent的scope.这样,Child就可以访问到Parent的scope中的所有函数和变量了. 需要注意的

[在读]用AngularJS开发下一代Web应用

内容简介 AngularJS是一款来自Google的前端JS框架,它的核心特性有:MVC.双向数据绑定.指令和语义化标签.模块化工具.依赖注入.HTML模板,以及对常用工具的封装,例如$http.$cookies.$location等.AngularJS框架的体积非常小,但是设计理念和功能却非常强大,值得前端开发者深入学习. <用AngularJS开发下一代Web应用>对AngularJS框架的核心特性做了全面的介绍,包括常用的开发工具和开发环境.<用AngularJS开发下一代Web应

ngxin开发笔记_配置项

ngxin开发笔记_配置项 模块的配置项即nginx.conf中的指令,HTTP模块指令可以分为三个级别: main级,直接写在http{}块中的指令 server级,写在server{}块中的指令 location级,写在location{}块中的指令 配置项定义模板 在自定义模块中使用配置项,需要配置ngx_module_t的commands属性以及ctx属性,并需要定义一个结构体用于存放配置信息. 常用的模板如下: /* 存放配置信息的自定义结构体 */ typedef struct {