学习笔记-angular自定义指令

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 方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容