AngularJs编写指令

 1 <!DOCTYPE html>
 2 <html ng-app="app">
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6    <script src="js/angular1.3.14.min.js"></script>
 7   </head>
 8   <body>
 9 <gys-directive></gys-directive>
10 <pp-directive value="www.baidu.com" text="链接一"></pp-directive>
11 <div pp-directive value="www.gugou.com" text="链接二"></div>
12 <script>
13     var appModule=angular.module("app",[]);
14      appModule.directive("gysDirective", function () {
15         return{
16             replace:true,
17           restrict:"E",
18             template:"<a href='http:ww.baidu.com'>百度</a>"
19         };
20     }).directive("ppDirective", function () {
21         return{
22             replace:true,
23             restrict:"EAC",
24             template:function(elem,attr){
25                 return "<a href='"+attr.value+"'>"+attr.text+"</a>";
26             }
27         };
28     });
29 </script>
30 </body>
31 </html>

重点在于上面的return.

下面看看return中的所有的参数.

 1 { 
 2         restrict: String, 
 3         priority: Number, 
 4         terminal: Boolean, 
 5         template: String or Template Function: 
 6     function(tElement, tAttrs) {...}, 
 7     templateUrl: String, 
 8     replace: Boolean or String, 
 9     scope: Boolean or Object, 
10     transclude: Boolean, 
11     controller: String or 
12     function(scope, element, attrs, transclude, otherInjectables) { ... }, 
13     controllerAs: String, 
14     require: String, 
15     link: function(scope, iElement, iAttrs) { ... }, 
16     compile: // 返回一个对象或连接函数,如下所示:
17     function(tElement, tAttrs, transclude) { 
18         return { 
19             pre: function(scope, iElement, iAttrs, controller) { ... }, 
20             post: function(scope, iElement, iAttrs, controller) { ... } 
21            } 
22         return function postLink(...) { ... } 
23         } 
24     }

restrict是一个可选的参数。用于指定该指令在DOM中以何种形式被声明。默认值是A,即以属性的形式来进行声明。

E:<gys-directive></gys-directive>  标签

A: <div gys-directive="expression"></div>  属性

C: <div class="gys-directive:expression;"></div>  类名

M:<!--directive:gys-directive expression-->

priority:大多数指令会忽略这个参数,使用默认值0,但也有些场景设置高优先级是非常重要甚至是必须的。例如,ngRepeat将这个参数设置为1000,这样就可以保证在同一元素上,它总是在其他指令之前被调用。

terminal:这个参数用来停止运行当前元素上比本指令优先级低的指令。但同当前指令优先级相同的指令还是会
被执行。例如:ngIf的优先级略高于ngView(它们操控的实际就是terminal参数),如果ngIf的表达式值为
true,ngView就可以被正常执行,但如果ngIf表达式的值为false,由于ngView的优先级较低就不会被执行。

template:参数是可选的,必须被设置为以下两种形式之一:

  •  一段HTML文本;
  • 一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个代表模板的字符串。tElement和tAttrs中的t代表template,是相对于instance的。

上面例子中都有.

templateUrl是可选的参数,可以是以下类型:
    一个代表外部HTML文件路径的字符串;
    一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个外部HTML文件路径的字符串。

replace:是一个可选参数,如果设置了这个参数,值必须为true,因为默认值为false。默认值意味着模板会被当作子元素插入到调用此指令的元素内部,

 transclude:除了替换和插入内容之外,还可以通过transclude属性将内容插入新的模板.当此属性设置为true的时候,指令中的字内容会被插入到,

ng-transclude的标签中.

上例中的结果是:

如果改成false.那么子内容将会被替换掉.

运行的结果:

一个示例点明了complie和link用法.(转载自:http://damoqiongqiu.iteye.com/blog/1917971)

css代码:

 1             .expander {
 2     border: 1px solid black;
 3     width: 250px;
 4 }
 5 
 6 .expander>.title {
 7     background-color: black;
 8     color: white;
 9     padding: .1em .3em;
10     cursor: pointer;
11 }
12 
13 .expander>.body {
14     padding: .1em .3em;
15 }
16     

Html代码:

1 <div ng-controller="SomeController">
2             <expander class="expander" myname="思思博士" expander-title='title'>
3                 {{text}}
4             </expander>
5         </div>
 1 var appModule=angular.module('app',[]);
 2             appModule.directive('expander',function(){
 3                 return{
 4                     restrict:"EA",
 5                     replace:true,
 6                     transclude:true,
 7                     //下面这个scope到底是干嘛的 我是真看不出来了,希望知道的大神们给个解答啊.
 8                     scope:{
 9                         title:"=expanderTitle"
10                     },
11                     template:function(){
12                         var html='<div>';
13                         html+='<div class="title" ng-click="toggle()">{{title}}</div>';
14                         html+='<div class="body" ng-show="showMe" ng-transclude></div></div>';
15                          return html;
16                     },
17                     link:function(scope,element,attrs){
18                         alert(attrs.myname);
19                         scope.showMe=false;
20                         scope.toggle=function(){
21                             scope.showMe=!scope.showMe;
22                         }
23                     }
24                 }
25             });
26             
27             appModule.controller("SomeController",function($scope){
28                 $scope.title="点击展开";
29                 $scope.text="这是内部的内容.";
30             });

查看界面:

controller:参数可以是一个字符串或一个函数。当设置为字符串时,会以字符串的值为名字,来查找注册在应用中的控制器的构造函数

1 angular.module('myApp', []) 
2 .directive('myDirective', function() { 
3 restrict: 'A',  
4 controller: 'SomeController' 
5 }) 

可以在指令内部通过匿名构造函数的方式来定义一个内联的控制器

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

我们可以将任意可以被注入的ng服务注入到控制器中,便可以在指令中使用它了。控制器中也有一些特殊的服务可以被注入到指令当中。这些服务有:

1. $scope

与指令元素相关联的当前作用域。
2. $element
当前指令对应的元素。
3. $attrs
由当前元素的属性组成的对象。

1 <div id="aDiv"class="box"></div>
2 具有如下的属性对象:
3 { 
4 id: "aDiv", 
5 class: "box" 
6 } 

4. $transclude
嵌入链接函数会与对应的嵌入作用域进行预绑定。transclude链接函数是实际被执行用来克隆元素和操作DOM的函数。

 1 angular.module('myApp',[])
 2  .directive('myLink', function () {
 3      return {
 4          restrict: 'EA',
 5          transclude: true,
 6          controller:
 7          function ($scope, $element,$attrs,$transclude) {
 8              $transclude(function (clone) {              
 9                  var a = angular.element('<a>');
10                  a.attr('href', $attrs.value);
11                  a.text(clone.text());
12                  $element.append(a);
13              });
14          }
15      };
16  });
  <my-link value="http://www.baidu.com">百度</my-link>
  <div my-link value="http://www.google.com">谷歌</div>

controllerAs参数用来设置控制器的别名,这样就可以在视图中引用控制器甚至无需注入$scope。

<div ng-controller="MainController as main">
        <input type="text" ng-model="main.name" />
        <span>{{ main.name }}</span>
    </div> 

javascript:
  angular.module('myApp',[])
   .controller('MainController', function () {
       this.name = "Halower";
   });

控制器的别名使路由和指令具有创建匿名控制器的强大能力。这种能力可以将动态的对象创建成为控制器,并且这个对象是隔离的、易于测试。

 require为字符串代表另外一个指令的名字。require会将控制器注入到其所指定的指令中,并作为当前指令的链接函数的第四个参数。字符串或数组元素的值是会在当前指令的作用域中使用的指令名称。在任何情况下,ng编译器在查找子控制器时都会参考当前指令的模板。

  • 如果不使用^前缀,指令只会在自身的元素上查找控制器。指令定义只会查找定义在指令作当前用域中的ng-model=""
  • 如果使用?前缀,在当前指令中没有找到所需要的控制器,会将null作为传给link函数的第四个参数。
  • 如果添加了^前缀,指令会在上游的指令链中查找require参数所指定的控制器。
  •  如果添加了?^ 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找
  • 如果没有任何前缀,指令将会在自身所提供的控制器中进行查找,如果没有找到任何控制器(或具有指定名字的指令)就抛出一个错误

一个综合示例.和上面的示例同样来自一个地方.

js代码:

 1 var expModule=angular.module('expanderModule',[])
 2 expModule.directive('accordion', function() {
 3     return {
 4         restrict : 'EA',
 5         replace : true,
 6         transclude : true,
 7         template : '<div ng-transclude></div>',
 8         controller : function() {
 9             var expanders = [];
10             this.gotOpened = function(selectedExpander) {
11                 angular.forEach(expanders, function(expander) {
12                     if (selectedExpander != expander) {
13                         expander.showMe = false;
14                     }
15                 });
16             }
17             this.addExpander = function(expander) {
18                 expanders.push(expander);
19             }
20         }
21     }
22 });
23 
24 expModule.directive('expander', function() {
25     return {
26         restrict : 'EA',
27         replace : true,
28         transclude : true,
29         require : '^?accordion',
30         scope : {
31             title : '=expanderTitle'
32         },
33         template : '<div>'
34                    + '<div class="title" ng-click="toggle()">{{title}}</div>'
35                    + '<div class="body" ng-show="showMe" ng-transclude></div>'
36                    + '</div>',
37         link : function(scope, element, attrs, accordionController) {
38             scope.showMe = false;
39             accordionController.addExpander(scope);
40             scope.toggle = function toggle() {
41                 scope.showMe = !scope.showMe;
42                 accordionController.gotOpened(scope);
43             }
44         }
45     }
46 });
47 
48 expModule.controller("SomeController",function($scope) {
49     $scope.expanders = [{
50         title : 'Click me to expand',
51         text : 'Hi there folks, I am the content that was hidden but is now shown.'
52     }, {
53         title : 'Click this',
54         text : 'I am even better text than you have seen previously'
55     }, {
56         title : 'Test',
57         text : 'test'
58     }];
59 });

HTML代码:

 1 <html ng-app="expanderModule">
 2     <head>
 3         <meta http-equiv="content-type" content="text/html; charset=utf-8" />
 4         <script src="../angular-1.0.3/angular.min.js"></script>
 5         <link rel="stylesheet" type="text/css" href="Accordion.css"/>
 6     </head>
 7     <body ng-controller='SomeController' >
 8         <accordion>
 9             <expander class='expander' ng-repeat='expander in expanders' expander-title='expander.title'>
10                 {{expander.text}}
11             </expander>
12         </accordion>
13     </body>
14     <script src="Accordion.js"></script>
15 </html>

css代码:

 1 .expander {
 2     border: 1px solid black;
 3     width: 250px;
 4 }
 5 
 6 .expander>.title {
 7     background-color: black;
 8     color: white;
 9     padding: .1em .3em;
10     cursor: pointer;
11 }
12 
13 .expander>.body {
14     padding: .1em .3em;
15 }

原文地址:https://www.cnblogs.com/guoyansi19900907/p/4674635.html