PHP群:95885625 Hbuilder+MUI群:81989597 站长QQ:634381967
    您现在的位置: 首页 > 开发编程 > AngularJS教程 > 正文

    AngularJS 自定义指令详解

    作者:admin来源:网络浏览:时间:2020-09-30 00:07:50我要评论
    导读:除了 AngularJS 内置的63个指令外,我们还可以创建自定义指令。你可以使用 .directive 函数来添加自定义的指令。要调用自定义指令,HTM...
    除了 AngularJS 内置的63个指令外,我们还可以创建自定义指令。你可以使用 .directive 函数来添加自定义的指令。要调用自定义指令,HTML 元素上需要添加自定义指令名。使用驼峰法来命名一个指令, runoobDirective, 但在使用它时需要以 - 分割, runoob-directive,自定义指令的参数如下:

    1. angular.module('app', []).directive('myDirective'function() {   
    2.     return {   
    3.     restrict:String,                   
    4.     priority:Number,   
    5.     terminal:Boolean,   
    6.     template:String or Template Function,   
    7.     templateUrl:String or Template Function,   
    8.     replace:Boolean or String,   
    9.     transclude:Boolean,   
    10.     scope:Boolean or Object,   
    11.     controller:String or function(scope, element, attrs, transclude, otherInjectables) { ... },   
    12.     controllerAs:String,   
    13.     require:String,   
    14.     link: function(scope, iElement, iAttrs) { ... },   
    15.     compile:function(tElement, tAttrs, transclude) {   
    16.         return {   
    17.             pre: function(scope, iElement, iAttrs, controller) { ... },   
    18.             post: function(scope, iElement, iAttrs, controller) { ... }   
    19.            }   
    20.         return function postLink(...) { ... }   
    21.         }   
    22.     };   
    23.  });   

    1、restrict:String

    restrict是申明标识符在模板中作为元素,属性,类,注释或组合,如何使用。有四个值:E、A、C、M

    AngularJS 自定义指令详解

    注意:

    (1)、推荐使用元素和属性的方式使用指令

    (2)、当需要创建带有自己的模板的指令时,使用元素名称的方式创建指令

    (3)、当需要为已有的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. </body>   
    12. <script src="framework/angular-1.3.0.14/angular.js"></script>   
    13. <script>   
    14. var myModule = angular.module("MyModule", []);   
    15.         myModule.directive("hello"function() {   
    16.            return {   
    17.             restrict: 'AEMC',   
    18.             template: '<div>Hi everyone!</div>',   
    19.             replace: true   
    20.            }   
    21.         });   
    22. </script>   
    23. </html>   

    AngularJS 自定义指令详解
    2、priority: Number

    priority是指令执行优先级。若在单个DOM上有多个指令,则优先级高的先执行;

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

    3、template: String or Function

    (1)、字符串

    template是指令链接DOM模板
     

    1. <!doctype html>   
    2. <html ng-app="MyModule">   
    3. <head>   
    4. <meta charset="utf-8">   
    5. </head>   
    6. <body>   
    7. <hello></hello>   
    8. </body>   
    9. <script src="framework/angular-1.3.0.14/angular.js"></script>   
    10. <script>   
    11. var myModule = angular.module("MyModule", []);   
    12. myModule.directive("hello"function() {   
    13.   return {   
    14.        restrict: 'E',   
    15.        template: '<div>hello world</div>',   
    16.        replace: true   
    17.   }   
    18. });   
    19. </script>   
    20. </html>   

    (2)、函数

    Function一个函数,可接受两个参数tElement和tAttrs。其中tElement是指使用此指令的元素,而tAttrs则实例的属性,它是一个由元素上所有的属性组成的集合(对象)形如:
     

    1. {   
    2.   name:‘shanshuizinong,   
    3.   age:23   
    4. }   
    1. <!doctype html>   
    2. <html ng-app="MyModule">   
    3. <head>   
    4. <meta charset="utf-8">   
    5. </head>   
    6. <body>   
    7. <hello name='shanshuizinong'></hello>   
    8. </body>   
    9. <script src="js/angular.min.js"></script>   
    10. <script>   
    11. var myModule = angular.module("MyModule", []);   
    12.         myModule.directive("hello"function() {   
    13.            return {   
    14.             restrict: 'E',   
    15.             replace: true,   
    16.             template: function(tElement,tAttrs){   
    17.                     var html = '';   
    18.                     html += '<div>'+tAttrs.name+'</div>';   
    19.                     return html;   
    20.                  }   
    21.            }   
    22.         });   
    23. </script>   
    24. </html>   

    AngularJS 自定义指令详解
    4、emplateUrl: String

    templateUrl是指定一个字符串式的内嵌模板,如果你指定了模板是一个URL,那么是不会使用的。
     

    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. <hello></hello>   
    9. </body>   
    10. <script src="framework/angular-1.3.0.14/angular.js"></script>   
    11. <script type="text/javascript">   
    12. var myModule = angular.module("MyModule", []);   
    13.     myModule.directive("hello"function() {   
    14.       return {   
    15.         restrict: 'AECM',   
    16.         templateUrl: 'hello.html',   
    17.         replace: true   
    18.      }   
    19.     });   
    20. </script>   
    21. </html>  

    AngularJS 自定义指令详解

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

    1. <!doctype html>   
    2. <html ng-app="MyModule">   
    3. <head>   
    4. <meta charset="utf-8">   
    5. </head>   
    6. <body>   
    7. <hello></hello>   
    8. </body>   
    9. <script src="framework/angular-1.3.0.14/angular.js"></script>   
    10. <script type="text/javascript">   
    11.   var myModule = angular.module("MyModule", []);   
    12.       //注射器加载完所有模块时,此方法执行一次;缓存   
    13.       myModule.run(function($templateCache){   
    14.      $templateCache.put("hello.html","<div>Hello world!!!</div>");   
    15.       });   
    16.       myModule.directive("hello"function($templateCache) {   
    17.          return {   
    18.            restrict: 'AECM',   
    19.            template: $templateCache.get("hello.html"),   
    20.            replace: true   
    21.          }   
    22.       });   
    23. </script>   
    24. </html>   

    AngularJS 自定义指令详解

    5、replace: Boolean

    replace是指令链接模板是否替换原有元素

     

    1. <!doctype html>   
    2. <html ng-app="MyModule">   
    3. <head>   
    4. <meta charset="utf-8">   
    5. </head>   
    6. <body>   
    7. <hello>   
    8. <div>这里是指令内部的内容。</div>   
    9. </hello>   
    10. </body>   
    11. <script src="js/angular.min.js" type="text/javascript" charset="utf-8"></script>   
    12. <script type="text/javascript">   
    13. var myModule = angular.module("MyModule", []);   
    14.     myModule.directive("hello"function() {   
    15.       return {   
    16.         restrict:"AE",   
    17.         template:"<div>Hello World!</div>",   
    18.         replace:true   
    19.       }   
    20.     });   
    21. </script>   
    22. </html>   

    AngularJS 自定义指令详解
    6、transclude: Boolean

    transclude是移动一个标识符的原始字节带到一个新模块的位置。当你开启transclude后,你就可以使用ng-transclude来指明了应该在什么地方放置transcluded内容。

    1. <!doctype html>   
    2. <html ng-app="MyModule">   
    3. <head>   
    4. <meta charset="utf-8">   
    5. </head>   
    6. <body>   
    7. <hello>   
    8. <div>这里是指令内部的内容。</div>   
    9. </hello>   
    10. </body>   
    11. <script src="js/angular.min.js"></script>   
    12. <script type="text/javascript">   
    13. var myModule = angular.module("MyModule", []);   
    14.     myModule.directive("hello"function() {   
    15.        return {   
    16.         restrict:"AE",   
    17.         transclude:true,   
    18.         template:"<div>Hello everyone!<div ng-transclude>你看不见我</div></div>"   
    19.        }   
    20.     });   
    21. </script>   
    22. </html>   

    AngularJS 自定义指令详解
    7、link:Function

    link通过代码修改目标DOM元素的实例,添加事件监听,建立数据绑定。compile函数用来对模板自身进行转换,而link函数负责在模型和视图之间进行动态关联;compile函数仅仅在编译阶段运行一次,而对于指令的每个实例,link函数都会执行一次;compile可以返回preLink和postLink函数,而link函数只会返回postLink函数,如果需要修改DOM结构,应该在postLink中来做这件事情,而如果在preLink中做这件事情会导致错误;大多数时候我们只要编写link函数即可。

    link函数有四个参数分别为:

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

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

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

    (4)supermanCtrl,若指令中定义有require选项,则会有supermanCtrl参数,代表控制器或者所依赖的指令的控制器。
     

    1. <!doctype html>   
    2. <html ng-app="MyModule">   
    3. <head>   
    4. <meta charset="utf-8">   
    5. </head>   
    6. <body>   
    7. <hello>Hello World!</hello>   
    8. </body>   
    9. <script src="js/angular.min.js"></script>   
    10. <script type="text/javascript">   
    11. var myModule = angular.module("MyModule", []);   
    12. myModule.directive("hello"function() {   
    13.   return {   
    14.   restrict:"AE",   
    15.   link:function(scope,element,attrs,supermanCtrl){   
    16.         console.log(element);   
    17.         element.bind("mouseenter",function(){   
    18.         console.log("鼠标进入...");   
    19.         });   
    20.         element.bind("mouseout",function(){   
    21.         console.log("鼠标滑出...");   
    22.         });   
    23.     }   
    24.   }   
    25. });   
    26. </script>   
    27. </html>   

    AngularJS 自定义指令详解
    下面实例通过link函数实现指令的复用,两个控制器与一个指令之间进行交互。指令可以调用控制器MyCtrl和MyCtrl2中的方法,但是需要注意我们必须使用属性,因为两个控制器的方法不同。
     

    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 type="text/javascript">   
    16. var myModule = angular.module("MyModule", []);   
    17. myModule.controller('MyCtrl', ['$scope'function($scope){   
    18.   $scope.loadData=function(){   
    19. console.log("加载数据中111...");   
    20.   }   
    21. }]);   
    22. myModule.controller('MyCtrl2', ['$scope'function($scope){   
    23.   $scope.loadData2=function(){   
    24.     console.log("加载数据中222...");   
    25.   }   
    26. }]);   
    27. myModule.directive("loader"function() {   
    28. return {   
    29. restrict:"AE",   
    30. link:function(scope,element,attrs){   
    31. element.bind('mouseenter'function(event) {   
    32.         //注意这里的坑,howToLoad会被转换成小写的howtoload   
    33.         scope.$apply(attrs.howtoload);   
    34.         });   
    35.         }   
    36.     }   
    37. });   
    38. </script>   
    39. </html>   

    AngularJS 自定义指令详解
    8、controller和require

    (1)、controller

    controller创建一个控制器通过标识符公开通信API。给指令暴露出一组public方法,给外部调用的。

    1)、字符串

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

    1. angular.module('myApp', []) .directive('myDirective'function() {   
    2. restrict: 'A',   
    3. controller: 'SomeController'   
    4. })   
    5. angular.module('myApp').controller('SomeController'function($scope, $element, $attrs, $transclude) {   
    6. // 控制器逻辑放在这里   
    7. });   

    2)、匿名函数

    也可以直接在指令内部的定义为匿名函数,同样我们可以再这里注入任何服务($log,$timeout等等)

    1. angular.module('myApp',[]) .directive('myDirective'function() {   
    2. restrict: 'A',   
    3. controller: function($scope, $element, $attrs, $transclude) {   
    4. // 控制器逻辑放在这里   
    5. }   
    6. });   

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

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

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

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

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

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

      指令的控制器和link函数可以进行互换。区别在于,控制器主要是用来提供可在指令间复用的行为但link链接函数只能在当前内部指令中定义行为,且无法再指令间复用。

    下面是实例js中包含controller的一部分:定义了三个公共方法,供外部指令访问。

     

    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. });   

    (2)、require

    require当前标识符需要另一个标识符提供正确的函数功能。require的值可以是字符串或者数组。字符串代表另一个指令的名字,它将会作为link函数的第四个参数。controller的用法分为两种情形,一种是require自定义的controller,由于自定义controller中的属性方法都由自己编写,使用起来比较简单;另一种方法则是require AngularJS内建的指令,其中大部分时间需要require的都是ngModel这个指令。

    下面是实例程序:假设现在我们要编写三个指令,三个指令中的link链接函数中存在有很多重合的方法,这时候我们就可以将这些重复的方法写在一个指令的controller中。然后在这三个指令中,require这个拥有controller字段的的指令,最后通过link链接函数的第四个参数就可以引用这些重合的方法了。

     

    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="js/angular.min.js"></script>   
    7. </head>   
    8. <body>   
    9. <div class="row">   
    10. <div class="col-md-3">   
    11. <superman strength>动感超人---力量</superman>   
    12. </div>   
    13. </div><br>   
    14. <div class="row">   
    15. <div class="col-md-3">   
    16. <superman strength speed>动感超人2---力量+敏捷</superman>   
    17. </div>   
    18. </div><br>   
    19. <div class="row">   
    20. <div class="col-md-3">   
    21. <superman strength speed light>动感超人3---力量+敏捷+发光</superman>   
    22. </div>   
    23. </div>   
    24. </body>   
    25. <script type="text/javascript">   
    26. var myModule = angular.module("MyModule", []);   
    27. myModule.directive("superman"function() {   
    28.     return {   
    29.         scope: {},   
    30.         restrict: 'AE',   
    31.         controller: function($scope) {   
    32.             $scope.abilities = [];   
    33.             this.addStrength = function() {   
    34.                 $scope.abilities.push("strength");   
    35.             };   
    36.             this.addSpeed = function() {   
    37.                 $scope.abilities.push("speed");   
    38.             };   
    39.             this.addLight = function() {   
    40.                 $scope.abilities.push("light");   
    41.             };   
    42.         },   
    43.         link: function(scope, element, attrs) {   
    44.             element.addClass('btn btn-primary');   
    45.             element.bind("mouseenter"function() {   
    46.                 console.log(scope.abilities);   
    47.             });   
    48.         }   
    49.     }   
    50. });   
    51. myModule.directive("strength"function() {   
    52.     return {   
    53.         require: '^superman',   
    54.         link: function(scope, element, attrs, supermanCtrl) {   
    55.             supermanCtrl.addStrength();   
    56.         }   
    57.     }   
    58. });   
    59. myModule.directive("speed"function() {   
    60.     return {   
    61.         require: '^superman',   
    62.         link: function(scope, element, attrs, supermanCtrl) {   
    63.             supermanCtrl.addSpeed();   
    64.         }   
    65.     }   
    66. });   
    67. myModule.directive("light"function() {   
    68.     return {   
    69.         require: '^superman',   
    70.         link: function(scope, element, attrs, supermanCtrl) {   
    71.             supermanCtrl.addLight();   
    72.         }   
    73.     }   
    74. });   
    75. </script>   
    76. </html> 

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


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

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

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

    (4)?^组合

    引用内置指令

    1. angular.module('myApp')     
    2. .directive('spoint'function() {     
    3.   return {     
    4.     require: 'ngModel',     
    5.     link: function(scope, elm, attrs, ctrl) {      
    6.       ctrl.$parsers.unshift(function(viewValue) {     
    7.         if (fibonacci.indexOf(parseInt(viewValue)) >= 0) {     
    8.           ctrl.$setValidity('fibonacci'true);     
    9.           return viewValue;     
    10.         } else {     
    11.           ctrl.$setValidity('fibonacci'false);     
    12.           return undefined;     
    13.         }     
    14.       });     
    15.     }     
    16.   };     
    17. });     

    这里值得注意的是directive里link方法的第四个参数,我们在require里定义了ngModel 所以这里它是一个NgModelController,NgModelController是用来为ng-model提供了一组API。

    转载请注明(B5教程网)原文链接:https://b5.mxunkeji.com/content-152-5190-1.html
    相关热词搜索: