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阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容