我爱编程

angular自定义指令

2017-08-14  本文已影响0人  LabRaDor2079
var app = angular.module("app",[]);
//第一个参数:指令的名称,使用驼峰命名
//第二个参数:回调函数,回调函数内部返回对象
app.directive("hiHello",function () {
        return {
        //执行的代码,参数,写在这里
        }
});

directive的参数

restrict : String

设置自定义指令的html格式

restrict的取值表
| E| C | M | A |
|:---------------:|:------:|
| element | attribute | class | 注释 |

<body>
    <!-- 1 : 使用指令的第一种方式 -->
    <hi-hello>若其中有内容,则被替换掉</hi-hello>
    <!-- 2: 属性 -->
    <div hi-hello></div>
    <!-- 3:类名 -->
    <div class="hi-hello"></div>
    <!-- 4:注释 指令名后面保留一个空格 -->
    <!-- directive:hi-hello -->
</body>
<script type="text/javascript">
    var app = angular.module("app",[]);
    app.directive("hiHello",function () {
            return {
                /* ECMA
                 * E : element
                 * A : attribute
                 * C : class
                 * M : 注释
                */

               restrict:"EACM",//可以组合使用,顺序不限,得大写 (默认值为EA)
                // 如果使用M,必须得配合使用 replace(替换)
                replace:true,//默认值为false  表示是否替换当前元素

                //设置模板
                template:"<h1>随便写的信息</h1>",
            }
        });
</script>

replace : Boolean or String

(布尔型)默认为false(模板内容会加载到标签内部),true(模板内容会替换当前标签),即是否替换当前元素中已有的内容

replace:true,
注意:如果使用M,必须得配合使用 replace(替换)
###priority : Number

优先级,可忽略,默认为0

注意: ng-repeat 的优先级为1000,这样就可以保证在同一元素上,它总是在其他指令之前被调用
###terminal : Boolean

如果为false,则Angular停止运行当前元素上比本指令优先级低的指令。优先级相同的指令还是会被执行

注意: ng-if 的优先级略高于 ng-view
priority和terminal的综合运用
<body>
    <hello well good>
        <div>Hello World!!!</div>
    </hello>
</body>
<script src="js/angular.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
    //terminal和priority两个参数只能在同一个元素上设置多个指令才有效
     app.directive("hello",function(){
         return {
                restrict : "E",
                priority : 1,
                link : function(){
                    console.log("hello");
                }
            }
    });
    app.directive("well",function(){
          return {
                restrict : "A",
                priority : 2,
                link : function(){
                    console.log("well");
                }
           }
    });
    app.directive("good",function(){
        return {
                restrict : "A",
                terminal : true, //这里为true,hello、well指令将停止执行
                priority : 3,
                link : function(){
                    console.log("good");
                }
        }
      });
      app.controller("myCtrl",function($scope){

    })
</script>

template : String or Template Function

设置模板,必须设置

template:"<h1>随便写的信息</h1>",
//template:function(tElement, tAttrs){...},
###templateUrl: String

(字符串或函数)

外部路径的字符串
接受两个参数的函数,参数为 tElement 和 tAttrs ,并返回一个外部HTML文件路径的字符串
模板加载后,AngularJS会将它默认缓存到$templateCach服务中。

注意:templateUrl 可以提前加载模块到缓存中,提高加载速度
templateUrl : "html/first.html",
###scope: Boolean or Object

当一个控制器实现多个数据时,就需要用到scope属性实现不同的数据。如果要创建一个能够从外部原型继承作用域的指令,将 scope 属性设置为 true

scope属性的独立作用域

为true时,从父作用域继承并创建一个自己的作用域
为false(默认)时,全部继承父作用域
1).controller属性
配置属于每个指令自己作用域上的数据(共有),而ng-controller 的作用就是从父级作用域继承并创建一个新的子作用域。

controller : function($scope){
      $scope.age = 20
}

设置为一个对象,则能设置 隔离作用域, scope 属性设置为一个空对象 {} 。如果这样做了,指令的模板就无法访问外部作用域了,代码如下:

directive('myDirective', function() {
      return {
              restrict: 'A',
              scope: {},
              priority: 100,
              template: '<div>Inside myDirective {{ myProperty }}</div>'
      };
});

隔离作用域

将scope属性设置为一个对象,而不是布尔值。隔离作用域默认和父作用域没关系,无法继承它的属性

1). 设置模板中数据的作用域和绑定规则:
|@| = |&|
|:---------------:|:------:|
| 把当前属性作为字符串传递 |与父作用域中的属性进行绑定素|与父作用域中的函数进行绑定|

"@" : 本地作用域属性:使用当前指令中的数据和DOM属性的值进行绑定
“=” : 双向绑定:本地作用域上的属性同父级作用域上的属性进行双向的数据绑定。
“&” : 父级作用域绑定:通过 & 符号可以对父级作用域进行绑定

scope : {
        name : "@"  //属性和标签内的属性写一样
}
scope: {
      ngModel: '=', // 将ngModel同指定对象绑定
      onSend: '&', // 将引用传递给这个方法
      fromName: '@' // 储存与fromName相关联的字符串
}

transclude: Boolean

默认为false,需要创建一个可以包含任意内容的指令时, 才使用 transclude: true 。

注意:只要使用了 transclude 参数,那么在控制器(下面马上会介绍)中就无法正常监听数据模型的变化了

controller: String or function

controller: String or function(scope, element, attrs, transclude, otherInjectables) { ... }

注册在应用中的控制器的构造函数,使用函数创建内联控制器

angular.module('myApp',[]).directive('myDirective', function() {
             restrict: 'A',
            controller:function($scope, $element, $attrs, $transclude) {
                  // 控制器逻辑放在这里
            }
})

controllerAs: String

可以在指令中创建匿名控制器

angular.module('myApp',[]).directive('myDirective', function() {
          return {
                  restrict: 'A',
                  template: '<h4>{{ myController.msg }}</h4>',
                  controllerAs: 'myController',
                  controller: function() {
                  this.msg = "Hello World"
          }
    };
});

require: String

(字符串或数组)字符串代表另外一个指令的名字,如果没有前缀,指令将会在自身所提供的控制器中进行查找,如果没有找到任何控制器(或具有指定名字的指令)就抛出一个错误。例如:

如果不使用 ^ 前缀,指令只会在自身的元素上查找控制器。
require: 'ngModel'
使用 ? 如果在当前指令中没有找到所需要的控制器,会将 null 作为传给 link 函数的第四个参数
require: '?ngModel'
使用 ^ 如果添加了 ^ 前缀,指令会在上游的指令链中查找 require 参数所指定的控制器。
require: '^ngModel'
使用 ^? 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找。
require: '^?ngModel',

link和compile

link: link: function(scope, iElement, iAttrs) { ... },
compile: compile: function(tElement, tAttrs, transclude) { ... },

compile 选项本身并不会被频繁使用,但是 link 函数则会被经常使用。当我们设置了 link 选项, 实际上是创建了一个 postLink() 链接函数, 以便 compile() 函数可以定义链接函数。
compile 和 link 选项是互斥的。如果同时设置了这两个选项,那么会把 - compile所返回的函数当作链接函数,而 link 选项本身则会被忽略。
通常情况下,如果设置了 compile 函数,说明我们希望在指令和实时数据被放到DOM中之前进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的。
//用 link 函数创建可以操作DOM的指令。

require  : 'SomeController',
link: function(scope, element, attrs, SomeController) {
         // 在这里操作DOM,可以访问required指定的控制器
}
compile: function(tElement, tAttrs, transclude) {  
        return {
            pre: function(scope, iElement, iAttrs, controller) { ... },
            post: function(scope, iElement, iAttrs, controller) { ... }
        }
        // 或者
        return function postLink(...) { ... }
    }
};

注意:指令的生命周期开始于 $compile 方法并结束于 link 方法

上一篇下一篇

猜你喜欢

热点阅读