angular js自定义指令

来源:互联网 发布:阿里云香港翻墙 编辑:程序博客网 时间:2024/05/17 03:52

(1)自定义指令实质

               说白了就是把自定义的指定替换成浏览器可以识别的HTML标签


(2)实例1(基本使用)

<!DOCTYPE html><html ng-app="myTest"><head>    <meta charset="utf-8">    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script></head><body>    <hello></hello>    <script type="text/javascript">        var app = angular.module('myTest', [])        app.directive("hello",function(){            return {                restrict:'E',                template:'<div>hi angular</div>',                replace:true            }        });    </script></body></html>
              对于<hello>标签浏览器是不认识的,所以浏览器唯一能够做的就是忽略这个标签,那么为了要让浏览器认识这个标签,我们需要使用angular js来定义hello指令。
            运行之后的结果如下:

           

           可以看出,<hello>实际上被替换为了<div>hi angular</div>,实际上这就是replace:true的作用

           那么替换的内容是从哪里来的呢?显然就是template中定义的

           还剩一个restrict意思就是我们定义的指令可以作为什么形式使用

     可选的值有四个,即AECM。

    A attribute属性:当做属性来使用

   <div hello></div>

   E element元素:当做标签元素来使用

   <hello></hello>

  C class类:当做CSS样式来使用

  <div class="hello"></div>

  M comments注释:当做注释使用(这种方式在1.2版本下亲测不可用!)

  <!-- directive:hello -->  <div></div>

     一般来说推荐,当做属性和元素来使用。

  当想要在现有的html标签上扩展属性时,采用属性的方式。

  当想要自定义标签时,采用标签的形式。

  想要使用那种方式,必须要在定义directive中的restrict里面声明对应的字母


(3)实例2(transclude)

             假如当前我们自定义了标签,但是标签中还含有子标签,如下,这时怎么在替换的时候仍然包含其中的子标签呢?

<!DOCTYPE html><html ng-app="myTest"><head>    <meta charset="utf-8">    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script></head><body>    <hello>        <span>标签中原来内容1</span>        <span>标签中原来内容2</span>    </hello></body></html>
              这时可以使用transclude:true,同时将原来内容嵌套在指定位置来实现
<!DOCTYPE html><html ng-app="myTest"><head>    <meta charset="utf-8">    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script></head><body>    <hello>        <span>标签中原来内容1</span>        <span>标签中原来内容2</span>    </hello>    <script type="text/javascript">        var app = angular.module('myTest', [])        app.directive("hello",function(){            return {                restrict:'E',                template:'<div>hi <span ng-transclude></span> angular</div>',                transclude:true            }        });    </script></body></html>
           结果如下

       
         生成的结构如下:

            

         

(4)实例3

             先看实例

<span style="font-size: 13.3333px;"><!DOCTYPE html><html ng-app="expanderModule"><head>    <meta charset="utf-8">    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script></head><body><div ng-controller='SomeController'>    <expander class='expander' expander-title='title'>        {{text}}    </expander></div>    <script type="text/javascript">        var expanderModule=angular.module('expanderModule', [])        expanderModule.directive('expander', function() {            return {                restrict : 'EA',                replace : true,                transclude : true,                scope : {                    title : '=expanderTitle'                },                template : '<div>'                + '<div class="title" ng-click="toggle()">{{title}},{{showMe}}</div>'                + '<div class="body" ng-show="showMe" ng-transclude></div>'                + '</div>',                link : function(scope, element, attrs) {                    scope.showMe = false;                    scope.toggle = function toggle() {                        scope.showMe = !scope.showMe;                    }                }            }        });        expanderModule.controller('SomeController',function($scope) {            $scope.title = '点击展开';            $scope.text = '这里是内部的内容。';        });    </script></body></html></span>

               看定义指令的源码,从上至下:

              1.scope

                 用来定义指令的作用域,可以定义false、true和对象,最常见的就是定义一个对象,其中可以从父作用域访问变量、函数
                 这时,scope的结构如下:

scope: {        ownAttributeName1: 'BINDING_STRATEGY+字符串',        ownAttributeName2: 'BINDING_STRATEGY+标签中属性名称',...}

                这其中的BINDING_STRATEGY指的是绑定策略,也就是说指令的scope中的值是从哪来的

                可以有3种取值

符号

说明

举例

@

传递一个字符串作为属性的值.

str : ‘@string’

=

使用父作用域中的一个属性,绑定数据到指令的属性中.

name : ‘=username’

&

使用父作用域中的一个函数,可以在指令中调用

getName : ‘&getUserName’

                比如本例中

scope : {                    title : '=expanderTitle'                }
               相当于指令scope中定义了一个名称为title的变量,就类似于在controller中定义变量$scope.name = "xxx"
               而使用的绑定策略是'=',就是说绑定了一个父作用域中的属性
               

               也就是说title绑定了标签中expander-title的值(这里注意一下,绑定时使用驼峰命名,标签中使用时使用连接线。使用指令时也是这样,如定义时使用myDerect,页面使用时使用my-derect

               然后发现其中expander-title和父scope中的title绑定了,那么最终指令中的值就是父scope中的值,即"点击展开"

               


              2.link

                 类似于controller中定义的function,完成指令scope的一些初始化工作

                template : '<div>'                + '<div class="title" ng-click="toggle()">{{title}},{{showMe}}</div>'                + '<div class="body" ng-show="showMe" ng-transclude></div>'                + '</div>',                link : function(scope, element, attrs) {                    scope.showMe = false;                    scope.toggle = function toggle() {                        scope.showMe = !scope.showMe;                    }                }

                 可以看到传入了scope(可以理解为指令中的类似controller中的$scope),接着就可以在其中像controller一样,对scope中的变量、函数进行定义了

                 定义完成之后,就可以在template或templateUrl定义的HTML中使用了


(5)require与controller

              1.引入

              假如现在需要写2个指令,而其中都需要toString()这个方法,那么该怎么办呢?

              显然不能每个指令的link中都定义一遍,那么能不能复用呢?

              require就是为了实现指令间功能复用而定义的

              而为了区别私有方法和公共方法,公共方法都写在controller中

              看如下实例

var app = angular.modeule('myapp',[]);app.directive('common',function(){    return {    ...    controller: function($scope){        this.method1 = function(){        };        this.method2 = function(){        };    },    ...    }});app.directive('d1',function(){    return {    ...    require: '?^common',    link: function(scope,elem,attrs,common){        scope.method1 = common.method1;        ..        },    ...    }});
           需要说明的是,link方法的第四个参数实际上就是common指令的controller对象
           可以发现,其中require使用了?^在公共模块名称前,这时告诉angular,^是往上寻找,找不到就抛异常;?表示找不到不会抛异常


             2.使用

                一般都是用在ngModel这个指令上,用来自定义验证等

              3.实例

<!DOCTYPE html><html ng-app="formCheckModule"><head>    <meta charset="utf-8">    <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script>    <script src="../lib/angular-messages.min.js"></script></head><body ng-controller='SomeController'><form name="userForm" novalidate >    <div class="form-group" ng-class="{'has-error':userForm.own.$touched && userForm.own.$invalid}">        <label>自定义</label>        <input type="text" name="own" class="form-control"               ng-model="main.own"               ng-maxlength="20" required               own />        <div ng-messages="userForm.own.$error" ng-if="userForm.own.$touched">            <p ng-message="isAdmin">测试不通过</p>        </div>    </div>    <div class="form-group">        <button type="submit" class="btn btn-danger">提交</button>    </div>    <pre>{{userForm.own.$error}}</pre></form>    <script type="text/javascript">        var formCheckModule=angular.module('formCheckModule', ['ngMessages']);        formCheckModule.controller('SomeController',function($scope) {        });        formCheckModule.directive("own",function(){            return {                require:'ngModel',                link:function(scope, element, attrs, modelController){                    var customValidator = function (value) {                        console.log(value);                        var validity = ('test'==(value));                        modelController.$setValidity("own", validity);                        return validity ? value : undefined;                    };                    modelController.$formatters.push(customValidator);                    modelController.$parsers.push(customValidator);                }            }        });    </script></body></html>          注意:1)函数中value就是表单中的数据
                2)每次表单中数据修改都会进入                3)$setValidity就是设置$error中的值

0 0
原创粉丝点击