AngularJS(十)自定义指令

var app = angular.module("directiveModule", []);
app.directive("helloWorld", function() {
    return {
        restrict: "ACE",
        replace: true, 
        template: "<h1> My First Custom Directive</h1>"
    }
});

directive()方法接收两个参数:第一个参数为指令名称,采用驼峰式命名法;第二个参数为指令定义方法,需要返回一个对象(成为指令定义对象DDO),用于描述指令的特征及指令对应的处理逻辑。我们可以向指令定义方法中注入一些依赖,例如$http、$rootScope等。

当我们的指令名称采用驼峰式命名法后,在指令使用时可以使用“-”或者“:”将多个单词隔开。

1. 指令定义对象(DDO)

1.1 restrict属性

指令使用形式有4种:

· E - Element元素:<hello-world></hello-world>

· A - Attribute属性:<div hello-world></div>

· C - Class样式:<div class="hello-word"></div>

· M - Comment注释: <!-- hello-world -->

1.2 replace属性

该属性用于指定是否使用template属性定义的HTML模板内容替换指令所在的HTML元素。

1.3 template属性

该属性指定AngularJS指令被替换成的HTML模板。template的HTML内容也可以使用指令和AngularJS表达式,AngularJS会先解析指令模板中的其他指定和表达式,然后把最终的结果输出到指令使用处。

2. 指令定义对象详解

2.1 link方法

像需要访问指令属性的情况就可以使用指令定义对象的link()方法。

html:

<say-hello name = "Smith"></say-hello>

js:

var app = angular.module("directiveModule",[]);
app.directive("sayHello", function(){
    return {
        restrict: "ACE",
        replace: true,
        template: "<h1>Hello , {{name}}</h1>"
        link: function(scope, elem, attrs){
            scope.name = attrs.name;
        }    
    }
});

三个参数:

· scope参数:表示指令作用域,默认情况下和父级作用域相同。当指令在ng-controller所在的元素开始标签和结束标签之间使用时,该指令会使用控制器对象的作用域,因此可以在link()方法中增加模型数据。在上面的代码中,我们在作用域对象中增加了一个name属性。

· elem参数:表示应用当前指令的HTML元素。并且是经过JQLite包装后的元素。JQLite是jQuery的一个子集,用于方便基本的DOM操作。如果想使用jQuery,只需通过<script>标签将jQuery库文件引入当前页面中,elem将会成为jQuery包装后的元素。

attrs参数:表示一个对象,包含指令的所有属性及属性值。

另外,link()方法的作用并不局限于此,还可以使用在以下场景:
· 需要获取或修改自定义指令属性时
· 当指令需要监视AngularJS作用域模型数据变化时
· 当指令需要响应HTML模板中元素单击、鼠标移动等事件时。

<!DOCTYPE html>
<html ng-app="directiveModule">
    <head> <meta charset="utf-8">
    <title>ch08_07</title>
    <script type="text/javascript" src="../../angular-1.5.5/angular.js"></script>
</head>
<body>
    <div>
        <hello-world></hello-world>
    </div>
    <script type="text/javascript">
        var app = angular.module("directiveModule", []);
        app.directive("helloWorld", function(){
         return {
             restrict: "ACE",
             replace: true,
            template: "<div><input type='text' ng-model='message' /><h1>Hello, world! {{message}}</h1><button ng-click='clearMessage()'>清除信息</button></div>",
             link: function(scope, elem, attrs) {
                 scope.$watch("message", function(value) { console.log("newValue:" + value); });
                 scope.clearMessage = function() { scope.message = ""; }
             }
         }
         });
    </script>
</body>
</html>

2.2 compile方法

AngularJS处理指令的过程。浏览器开始渲染HTML页面时,首先加载HTML元素、创建文档对象模型(DOM),加载完成后会触发onload事件。我们通过<script>标签将AngularJS引入HTML页面中,AngularJS就会监听onload事件,然后从DOM元素中查找ng-app指令,如果找到就启动AngularJS框架,接着从ng-app指令所在的HTML标签开始使用$compile服务遍历DOM元素。我们使用的directive()方法注册的指令都会保存在一个容器中,AngularJS会从这些DOM元素中识别哪些属于指令元素,AngularJS框架会根据指令定义对象决定如何处理这些指令。一旦所有的指令都被识别,就会执行指令定义对象的compile()方法。

所有指令的compile()方法只会在AngularJS框架启动时调用一次,该方法定义如下:

compile: function(tElem, tAttrs) {
    return {
        link: function(scope, iElem, iAttrs){}
    }
}

compile()方法可接收两个参数,含义如下:
· tElem:指令所在的元素
· tAttrs:指令元素的所有属性列表

compile()方法和link()方法有冲突,如果指定了指令定义对象的compile()方法就不能再为指令定义对象增加link()方法,但是link()方法可以由compile()方法作为返回值返回。

compile()方法只在AngularJS应用启动时执行一次,但是link()方法会针对每个被复制的实例执行,如果分开处理,就会在性能上有一定的提高。

compile()方法的主要作用是在link()方法执行之前对DOM元素进行修改,下面就用一个案例说明compile()方法的使用场合:


2.3 scope属性与指令作用域

默认情况下,指令直接使用父作用域。摆脱父作用域的两种方案:
· 使用子作用域从父作用域原型继承
· 使用孤立作用域,即创建一个新的作用域对象,和父作用域没有任何关系

var app = angular.module("app",[]);
app.directive("helloWorld", function(){
    return {
        scope: true,
        restrict: "AE",
        ……
    }
})

通过设置scope属性为true,将会为指令创建一个新的作用域,该作用域对象会从父作用域原型继承。

var app = angular.module("app",[]);
app.directive("helloWorld", function(){
    return {
        scope: {},
        restrict: "AE",
        ……
    }
})

通过将scope的属性设置为{},即可为指令创建一个孤立的作用域。

2.4 孤立作用域与父作用域模型数据绑定

· 使用@符号建立基于属性的绑定


或者

<say-hello name-attr="{{name}}"></say-hello>

scope: { name: "@nameAttr"}

· 使用=符号建立双向绑定

<say-hello name-attr="name"></say-hello>

scope: { name: "=nameAttr"}

· 使用&符号调用父作用域中的方法


2.5 Transclution

维基百科:在计算机科学中,Transclusion是指将整个或部分文档通过超文本引用包含到其他单个或多个文档中。


ng-transclude指令的作用其实就是把指令开始标签与结束标签之间的内容插入ng-transclude所在的位置。

transclude: element

该种情况表示把指令所作用的元素一同嵌入到ng-transclude指令所在的位置。此外,transclude属性默认为false。

更高级的使用暂未学习。

2.6 controller方法与require属性


3 自定义表单验证

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