angular js自定义指令

(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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值