分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

AngularJS 自定义指令详解

发布时间:2023-09-06 01:45责任编辑:董明明关键词:Angular指令AngularJS

版权声明:本文为博主原创文章,未经博主允许不得转载。 //blog.csdn.net/qq_27626333/article/details/52261409

除了 AngularJS 内置的63个指令外,我们还可以创建自定义指令。你可以使用 .directive 函数来添加自定义的指令。要调用自定义指令,HTML 元素上需要添加自定义指令名。使用驼峰法来命名一个指令, runoobDirective, 但在使用它时需要以 - 分割, runoob-directive,自定义指令的参数如下:

[javascript]view plaincopy
  1. angular.module(‘app‘,[]).directive(‘myDirective‘,function(){
  2. return{
  3. restrict:String,
  4. priority:Number,
  5. terminal:Boolean,
  6. template:StringorTemplateFunction,
  7. templateUrl:StringorTemplateFunction,
  8. replace:BooleanorString,
  9. transclude:Boolean,
  10. scope:BooleanorObject,
  11. controller:Stringorfunction(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. returnfunctionpostLink(...){...}
  21. }
  22. };
  23. });


1、restrict:String

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

注意:

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

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

(3)、当需要为已有的HTML标签增加功能时,使用属性的方式创建指令

实例:

[html]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. </head>
  6. <body>
  7. <hello></hello>
  8. <divhello></div>
  9. <div></div>
  10. <!--directive:hello-->
  11. </body>
  12. <scriptsrc="framework/angular-1.3.0.14/angular.js"></script>
  13. <script>
  14. varmyModule=angular.module("MyModule",[]);
  15. myModule.directive("hello",function(){
  16. return{
  17. restrict:‘AEMC‘,
  18. template:‘<div>Hieveryone!</div>‘,
  19. replace:true
  20. }
  21. });
  22. </script>
  23. </html>


2、priority: Number

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

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

3、template: Stringor Function

(1)、字符串

template是指令链接DOM模板

[html]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. </head>
  6. <body>
  7. <hello></hello>
  8. </body>
  9. <scriptsrc="framework/angular-1.3.0.14/angular.js"></script>
  10. <script>
  11. varmyModule=angular.module("MyModule",[]);
  12. myModule.directive("hello",function(){
  13. return{
  14. restrict:‘E‘,
  15. template:‘<div>helloworld</div>‘,
  16. replace:true
  17. }
  18. });
  19. </script>
  20. </html>

(2)、函数

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

[html]view plaincopy
  1. {
  2. name:‘shanshuizinong,
  3. age:23
  4. }


[javascript]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. </head>
  6. <body>
  7. <helloname=‘shanshuizinong‘></hello>
  8. </body>
  9. <scriptsrc="js/angular.min.js"></script>
  10. <script>
  11. varmyModule=angular.module("MyModule",[]);
  12. myModule.directive("hello",function(){
  13. return{
  14. restrict:‘E‘,
  15. replace:true,
  16. template:function(tElement,tAttrs){
  17. varhtml=‘‘;
  18. html+=‘<div>‘+tAttrs.name+‘</div>‘;
  19. returnhtml;
  20. }
  21. }
  22. });
  23. </script>
  24. </html>


4、emplateUrl: String

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

[html]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. <linkrel="stylesheet"href="css/bootstrap-3.0.0/css/bootstrap.css">
  6. </head>
  7. <body>
  8. <hello></hello>
  9. </body>
  10. <scriptsrc="framework/angular-1.3.0.14/angular.js"></script>
  11. <scripttype="text/javascript">
  12. varmyModule=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>


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

[html]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. </head>
  6. <body>
  7. <hello></hello>
  8. </body>
  9. <scriptsrc="framework/angular-1.3.0.14/angular.js"></script>
  10. <scripttype="text/javascript">
  11. varmyModule=angular.module("MyModule",[]);
  12. //注射器加载完所有模块时,此方法执行一次;缓存
  13. myModule.run(function($templateCache){
  14. $templateCache.put("hello.html","<div>Helloworld!!!</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>

5、replace: Boolean

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

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


6、transclude: Boolean

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

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


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参数,代表控制器或者所依赖的指令的控制器。

[html]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. </head>
  6. <body>
  7. <hello>HelloWorld!</hello>
  8. </body>
  9. <scriptsrc="js/angular.min.js"></script>
  10. <scripttype="text/javascript">
  11. varmyModule=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>


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

[html]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. </head>
  6. <body>
  7. <divng-controller="MyCtrl">
  8. <loaderhowToLoad="loadData()">滑动加载</loader>
  9. </div>
  10. <divng-controller="MyCtrl2">
  11. <loaderhowToLoad="loadData2()">滑动加载</loader>
  12. </div>
  13. </body>
  14. <scriptsrc="framework/angular-1.3.0.14/angular.js"></script>
  15. <scripttype="text/javascript">
  16. varmyModule=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>

8、controller和require

(1)、controller

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

1)、字符串

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

[javascript]view plaincopy
  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等等)

[javascript]view plaincopy
  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的一部分:定义了三个公共方法,供外部指令访问。

[javascript]view plaincopy
  1. varmyModule=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(‘btnbtn-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链接函数的第四个参数就可以引用这些重合的方法了。

[html]view plaincopy
  1. <!doctypehtml>
  2. <htmlng-app="MyModule">
  3. <head>
  4. <metacharset="utf-8">
  5. <linkrel="stylesheet"href="css/bootstrap-3.0.0/css/bootstrap.css">
  6. <scriptsrc="js/angular.min.js"></script>
  7. </head>
  8. <body>
  9. <div>
  10. <div>
  11. <supermanstrength>动感超人---力量</superman>
  12. </div>
  13. </div><br>
  14. <div>
  15. <div>
  16. <supermanstrengthspeed>动感超人2---力量+敏捷</superman>
  17. </div>
  18. </div><br>
  19. <div>
  20. <div>
  21. <supermanstrengthspeedlight>动感超人3---力量+敏捷+发光</superman>
  22. </div>
  23. </div>
  24. </body>
  25. <scripttype="text/javascript">
  26. varmyModule=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(‘btnbtn-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){
我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved