指令是什么?    指令是我们用来扩展浏览器能力的技术之一。在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----)
 

5.Angular-UI。

 
 
 复杂的指令终于结束了,Angular-UI封装了很多好的指令可以直接使用。省得自己挨个再写,费劲。关于详细的一些指令的用法,多看看API ,很好学。
希望自己越来越厉害,全能型人才即将诞生。哈哈哈哈!!
 
 

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

  1. AngularJS 开发中常犯的10个错误

    简介 AngularJS是目前最为活跃的Javascript框架之一,AngularJS的目标之一是简化开发过程,这使得AngularJS非常善于构建小型app原型,但AngularJS对于全功能的客 ...

  2. AngularJS开发最常犯的10个错误

    简介 AngularJS是目前最为活跃的Javascript框架之一,AngularJS的目标之一是简化开发过程,这使得AngularJS非常善于构建小型app原型,但AngularJS对于全功能的客 ...

  3. AngularJS常用插件与指令收集

    angularjs 组件列表 bindonce UI-Router Angular Tree angular-ngSanitize模块-$sanitize服务详解 使用 AngularJS 开发一个大 ...

  4. 带你走近AngularJS - 创建自己定义指令

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自己定义指令 ------------ ...

  5. 带你走近AngularJS 之创建自定义指令

    带你走近AngularJS 之创建自定义指令 为什么使用AngularJS 指令? 使用过 AngularJS 的朋友应该最感兴趣的是它的指令.现今市场上的前端框架也只有AngularJS 拥有自定义 ...

  6. 20个angularjs开发工具

    AngularJS是那些渴望以动态方式来设计web app的web开发人员最偏爱的框架之一.如果你是一个希望启动AngularJS项目的开发人员,那么你可能需要帮助来挑选出趁手的工具…… 在Value ...

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

    简介AngularJS是目前最为活跃的Javascript框架之一,AngularJS的目标之一是简化开发过程,这使得AngularJS非常善于构建小型app原型,但AngularJS对于全功能的客户 ...

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

    AngularJs开发——控制器间的通信 指令与控制器之间通信,无非是以下几种方法: 基于scope继承的方式 基于event传播的方式 service的方式 基于scope继承的方式 最简单的让控制 ...

  9. 实践分享:开始用Cordova+Ionic+AngularJS开发App

    http://www.cocoachina.com/webapp/20150707/12395.html 本文是一篇关于我本人在使用Cordova+Ionic以及AngularJS开发移动App的过程 ...

随机推荐

  1. GIT简单操作

    以下只是简单的bash的操作命令,个人比较喜欢用gui 打开 git bash here git clone https://github.com/自己的名字/trunk git checkout + ...

  2. 实现Windows Phone 8中ListBox的分页加载

    功能就是ListBox滚动到最下方的时候,能够自动加载下一页的内容. 解决问题的关键就是如何判断ListBox已经加载到了最底部. 网上找了两个解决方法: 1 http://googlers.itey ...

  3. c# 类型拷贝

    /// <summary> /// 类 名:EntityHelper /// 类 说 明:实体操作方法类 /// : /// 创建时间:2013/8/12 /// </summary ...

  4. Hibernate双向一对一对象关系模型映射

    一个员工一辆车:one-to-one 实现一:让汽车表中的外键唯一 create table emp ( eid int primary key auto_increment, ename varch ...

  5. objective-c数组

     1 #pragma mark -----------数组的初始化方式--------------  2 //        insert code here...  3 //        NSLo ...

  6. [Android Pro] 小心ReleaseByteArrayElements 中的参数问题

    referen to : http://blog.csdn.net/rainlight/article/details/818964 在Sun的官方文档中,关于该函数的用法如下 The array i ...

  7. October 4th 2016 Week 41st Tuesday

    Patience! The windmill never strays in search of the wind. 耐心等待!风车从不跑去找风. Sometimes we need to be pa ...

  8. python基础——继承和多态

    python基础——继承和多态 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类 ...

  9. JAVA作业02

    一,      课堂练习 (一)构造方法 1,源代码 public class Test{ public static void main(String[] args){ Foo obj1=new F ...

  10. HTTP1.0和HTTP1.1的主要区别是

    HTTP/.0协议使用非持久连接,即在非持久连接下,一个tcp连接只传输一个Web对象 HTTP/.1默认使用持久连接(然而,HTTP/.1协议的客户机和服务器可以配置成使用非持久连接)在持久连接下, ...