自定义指令的各种属性详解

【一】 自定义指令的两种方式

           1. 通过 module.directive(name,directiveFactory) 定义 , 如:        

         (function() {
           angular.module('starter')
             .directive('myCustomer', function() {
                return {
                   restrict: 'E',
                   templateUrl: 'directiveTest/my-customer.html'
            };
           })
          })()

           2. 注入 $compileProvider ,通过 $compileProvide.directive() 定义 , 如:

       var myApp = angular.module('myApp', [], ['$compileProvider',function ($compileProvider) {
         $compileProvider.directive('customTags',function(){
          return {
            restrict:'ECAM',
            template:'<div>custom-tags-html</div>',
            replace:false
          }
        });
      }])

【二】 restrict 、 template 、 replace、templateUrl属性

      var myApp = angular.module('myApp', [], ['$compileProvider',function ($compileProvider) {
       // 如果指令的名字为xxx-yyy 在设置指令的名字时应为 xxxYyy 驼峰式命名法
       $compileProvider.directive('customTags',function(){
         return {
            restrict:'ECAM',
            template:'<div>custom-tags-html</div>',
            replace:false,
            // templateUrl :加载模板所要使用的URL
            //replace :如果为true 则替换指令所在的元素,如果为false 或者不指定,则把当前指令追加到所在元素的内部


            //restrict :指令在模板中的使用方式
            //可以4种风格任意组合,如果忽略restrict,默认为A
            // E : 风格为 元素  (作为标签名)      使用方式: <custom-tags>1212</custom-tags>
            // C: 风格为 样式类                   使用方式: <div class="custom-tags"> </div>
            // A : 风格为 属性                    使用方式: <div custom-tags> </div>
            // M : 风格为 注释


            // 注意:当有两个directive的时候 只能有一个template,否则会报错
         }
        });
    }])
【三】transclude、priority、terminal 属性

           priority : 设置指令在模板中的执行顺序,顺序是相对于其他元素上的指令而言,默认为0,从大到小的顺序一次执行

           terminal : 是否以当前指令的权重为结束界限。如果这个值设置为true,则节点中权重小于当前指令的其他指令不会被执行。相同权重的会执行 

    .directive('customTags', function () {
        return {
            restrict: 'ECAM',
            template:'<div>新数据 <span ng-transclude></span></div>',
            replace: true,
            transclude:true
            //transclude:为true时,指令元素中的原来的子节点移动到一个新模板内部(移动到的位置通过ng-transclude确定)
            //priority 设置优先级
        }
    })

    .directive('customTags2', function () {
        return {
            restrict: 'ECAM',
            template:'<div>2</div>',
            replace: true,
            priority:0
        }
    })
    .directive('customTags3', function () {
        return {
            restrict: 'ECAM',
            template:'<div>3</div>',
            replace: true,
            priority: 1,
            // terminal 为true 时 priority 小于当前指令的priority的directive 都不会执行
            terminal:true
        }
    })
【四】 compile 和 link 属性

Angularjs 指令编译三个阶段

1.标准浏览器API转化
     将html 转化成dom ,所以自定义的html 标签必须符合html 的格式
2.Angular compile
     搜索匹配 directive ,按照priority排序,并执行directive上的compile 方法
3.Angular link
      执行directive上的link 方法,进行 scope绑定及事件绑定
   link 函数负责在模型和视图之间进行动态关联

     .directive('customTags',function(){
        return {
            restrict : 'ECAM',
            template : '<div>{{user.name}}</div>',
            replace : true,
            compile:function(tElement,tAttrs,transclude){
                // 1.编译阶段...主要可以进行DOM 结构的操作
                //  tElement.append(angular.element('<div>{{user.name}}{{user.count}}</div>'));
                console.log('customTags compile 编译阶段...');
                return {
                    //2.Link 包括 pre 和  post 主要可以用在添加事件的绑定和scope绑定

                    // 2.1.1表示在编译阶段之后,指令连接到子元素之前运行
                    pre:function preLink(scope,iElement,iAttrs,controller){
                        console.log('customTags preLink..')
                    },
                    // 2.1.2表示在所有子元素指令都连接之后才运行
                    post:function postLink(scope,iElement,iAttrs,controller){
                       iElement.on('click',function(){
                           //需要用 $apply触发一次 脏检查
                           scope.$apply(function(){
                               scope.user.name = 'click after';
                               scope.user.count = ++i;
                           });
                       })

                        console.log('customTags all child directive link..')
                    }
                }

                // 也可以直接返回 postLink
                // return function postction(scope,iElement,iAttrs,controller){
                //     console.log('compile return fun');
                // }
            },
            // 此link表示的就是 postLink
            // link:function postction(scope,iElement,iAttrs,controller){
            //    iElement.on('click',function(){
            //        scope.$apply(function(){
            //            scope.user.name = 'click after';
            //            scope.user.count = ++i;
            //            // 进行一次 脏检查
            //        });
            //    })
            // }
        }
      })
【五】controller 、controllerAs 和 require 属性 
     .directive('bookList', function() {
       return {
        restrict: 'ECAM',
        // controller 会暴露一个API ,利用这个API 可以在多个指令之间通过依赖注入进行通信
        controller: function($scope) {
            $scope.books = [{
                name: 'php'
            }, {
                name: 'javascript'
            }, {
                name: 'java'
            }];


            this.addBook = function() {


                $scope.$apply(function() {
                    $scope.books.push({
                        name: 'Angularjs'
                    })
                });
            }
        },
        controllerAs: 'bookListController',//controllerAs:给上面的controller 起个别名
        template: '<div><ul><li ng-repeat="book in books">{{book.name}}</li></ul><book-add></book-add></div>',
        replace: true
      }
     })


    .directive('bookAdd', function() {
      return {
        restrict: 'ECAM',
        require: '^bookList',
        //require 可以将其他指令传递给自己 ,如此可以去调用其他的指令的函数和修改其他指令的字段,实现不同指令之间的通信
        // (没有前缀)如果没有前缀,指令将会在自身所提供的控制器中进行查找,如果没有找到任何控制器就抛出一个错误。
        // ? 如果在当前指令中没有找到所需要的控制器,会将null作为传给link函数的第四个参数。
        // ^ 如果添加了^前缀,指令会在上游的指令链中查找require参数所指定的控制器。
        // ?^ 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找。
        template: '<button type="button">添加</button>',
        replace: true,
        link: function(scope, iElement, iAttrs, bookListController) {
            //点击调用第一个指令的addBook函数
            iElement.on('click', bookListController.addBook);
        }
      }
    })
【六】 scope 属性

           scope : 为当前指令创建一个新的作用域
           false : 继承父元素的作用域
           true : 创建一个新的作用域

          参数:
              &:作用域把父作用域的属性包装成一个函数,从而以函数的方式读写父作用域的属性
              =: 作用域的属性与父作用域的属性进行双向绑定,任何一方的修改均会影响到对方
              @:只能读取父作用域里的值单项绑定

           

    .directive('bookList', function () {
        return {
            restrict: 'ECAM',
            controller: function ($scope) {
                $scope.books = $scope.a();
                $scope.books = $scope.b;
                $scope.b.push({name:'nodejs'});
                console.log($scope.c);
            },
            // 创建一个有继承链的独立作用域
            // scope:true,

            // 当scope 为对象的时独立的作用域候也会创建一个
            scope:{
                // 将父元素books封装成一个a函数(&:作用域把父作用域的属性包装成一个函数,从而以函数的方式读写父作用域的属性)
                a:'&books'
                // 双向绑定 b = parentBooks属性对应的父作用域的表达式(=:作用域的属性与父作用域的属性进行双向绑定,
                //     任何一方的修改均会影响到对方)
                b:'=parentBooks'

                // 只能使用简单数据类型的方法,不能用对象(@ :只能读取父作用域里的值单向绑定)
                c:'@parentTitle'
            },
            controllerAs:'bookListController',
            template: '<div><ul><li ng-repeat="book in books">{{book.name}}</li></ul></div>',
            replace:true
        }
    })


    .controller('firstController', ['$scope', function ($scope) {
        console.log($scope);
        $scope.books = [
            {
                name: 'php'
            },
            {
                name: 'javascript'
            },
            {
                name: 'java'
            }
        ];
        $scope.title = '张三';

    }]);

       注意:html 文件中的属性写法要与指令中定义的相匹配。以上面的为例,html中:

 <div book-list books="books" parent-books="books" parent-title="{{title}}">

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值