接触AngularJS有一些时间了,但是对于其中一些知识点还是似懂非懂,比如关键的directive。之前用它搞了一下bootstrap里的自动完成功能(autocomplete),当时就感觉,嗯,这都是啥玩意。
directive
的作用
一般来讲,directives
是DOM元素上的标记,使AngularJS的HTML编译器为DOM绑定合适的动作,或者改变这个DOM。ngBind、ngModel、ngClass
就是Angular的内置directives
。当然也可以自定义directives。
Angular是靠HTML标记来区分不同的directives的,当碰到ng-model
的时候,就匹配到了ngModel
这个内置的directives
,调用内容即可。
等等,为什么上面是ngModel,到这里变成了ng-model?这是因为他们指向的同一个东西,相同的还可以用x-ng-model、data-ng-model、ng:model、ng_model
,效果都是一样的。另外,编译器还可以识别元素名、属性、class名或者注释。
这样的标记都是可以正常使用的。
那么,创建directives
,实际就是创建一个方法,去识别自己定义的标记。
如何写一个directive
写之前,需要先理解一下各个关键字的方法,对关键字的默认值和声明方式,这里有个说明。
总体看来,它的属性还是挺多的,而且像controller、scope、link、transclude
都是一些看起来好像很简单,但是十分灵活的属性,比单纯的true/false的属性设置要来的复杂很多。下面是一些关键字的理解。
关键字restrict
restrict
用于说明directive
以何种方式声明(元素名、属性、class名或者注释)。比如,我有一个directive
声明如下:
.directive('myDirective', function() { ...... });
那么,我在HTML这边,就能直接用默认的my-directive
这样的标记来写,当然上面列出的使用属性、class、注释等来写也是可以的。要使用这些,需在directive
里使用restrict
属性来区分。
restrict
共有4个值,可以混合使用,比如AE、ACM、AEC等等。
‘A’ – only matches attribute name
‘E’ – only matches element name
‘C’ – only matches class name
‘M’ – only matches comment
那么,如果用这四种方式来声明,那么HTML的代码就是这样:
'A': 'E': 'C': 'M':
关键字template
和templateUrl
作为directive
(指导),有时候需要指定一个template
(模板)。这个模板可以直接写,也可以调用其他文件中定义的模板,这就是这两个关键字的用处。比如我定义了一个
$scope.customer = { name: 'Naomi', address: '1600 Amphitheatre' };
就可以在directive
里使用
template: 'Name: {{customer.name}} Address: {{customer.address}}'
来指定返回内容的格式。或者把这个template的内容写到一个html中,那就可以用templateUrl
来指定这个模板地址。
关键字scope
scope这个字段,感觉是要创建一个局部的scope
变量(isolate scope),不同的是,这个变量与父变量(copy from)可以单向绑定或者双向绑定。关于scope
的说明,在这里。
scope
的声明方法,有4种:
@ 或 @attr
绑定这个DOM的attr属性。比如这个DOM有attr=”hello {{name}}”,这个name是全局的变量,directive里有scope: { localName:’@attr’ }那么绑定之后,对于name的改变,也会改变localName的值,
= 或 =attr
建立本地的双向绑定,DOM需要有attr=”name”,这个name是全局的变量,那么有scope: { localName:’=attr’ }之后,localName就和这个全局的name建立了双向绑定,任一方的更改会影响到对方的值。
'<' 或 '< attr'
单向绑定,只把attr包含的变量赋于本地scope变量,任何对于全局name的改变都会影响到localName,但是对于localName的改变不会影响到全局name的值。
& 或 &attr
可以在attr中指定表达式。
关键字transclude
transclude
可以使这个directive
可以包裹(wrap)其他元素。这里包裹的意思,就是将元素原来的内容移动到template
里面的任意位置,这里有个例子。
当这个关键字为false
的时候,则会直接覆盖原来的内容。
关键字controller、require、link
一堆代码看下来,controller
是使用频率比较高的一个属性,它用于在directive
里定义一个暴露出来的方法,相当于给它伸出了一个API,可以直接供其他directive
调用。当然作为调用,需要先引用一下源,require就是这个作用,在require里做了声明,才能调用到相应directive
里的API。
在调用时候,需要使用关键字link
,例如
link: function(scope, element, attrs, tabsCtrl) {tabsCtrl.xxController();}
当require传入的是一个数组的时候['dep1','dep2']
,则调用时使用tabsCtrl[0].xxController();
这样的形式。
关键字compile
在link执行之前执行,用于动态修改template
。