directive 是 angular 中最重要的一部分,也是最难的部分。Angular 内部封装了一些指令,例如 ng-model ng-class ng-click
。Angular 内部指令大部分都是以 ng 开头的。
directive 匹配方式
按照 Angular 的标准,指令的命名规则是以驼峰式命名的(例如ngModel
)。然而,由于 HTML 是不区分大小写的,因此通常用一个 DOM 元素的划线分隔属性(例如ng-model
)。
Angular 匹配指令过程如下:
1、去除元素或属性的前缀data-
和x-
2、将: _ -
连接字符串转换成驼峰表现形式
因此通常在使用中可以写成以下几种形式:
ng-model
ng:model
ng_model
data-ng-model
x-ng-model
directive 种类
$compile
可以基于标签、属性、类名 、注释匹配 directive。
<my-directive></my-directibe> // 元素
<div my-directive='exp'></div> // 属性
<div class='my-directive'></div> // 类名
<!-- directive:my-directive exp --> // 注释
建议更多的使用标签和属性类型的指令。
创建自定义 directive
指令注册的方式与 controller 一样,但是它返回的是一个拥有指令配置属性的简单对象(指令定义对象) 。
下面的代码是一个简单的 myDirective 指令。
var app = angular.module('directive', []);
app.directive('myDirective', function() {
return {
template: '<div></div>',
restrict: 'E',
link: function postLink(scope, element, attrs) {
element.text('my directive!!');
}
}
})
这个指令在 HTML 中以一个元素使用,如下
其中 template
,restrict
,link
都是指令配置属性,还有其他的属性,我们对其逐一的解释,属性名称下的第一行分别是属性名称、属性类型、默认值。
multiElement
多元素、boolean
、false
当此属性设置为 true 时,HTML 编译器将收集在directive-name-start
和directive-name-end
两个属性之间的 DOM 节点,并将它们组一起作为指令元素。
建议将此功能应用于行为不严格的指令(如ngclick
),和
不处理或更换子节点(如nginclude
)。
-
priority
优先级、number
、0
当有多个 directive 定义在同一个 DOM 元素上时,有时需要明确他们的执行顺序。
这个属性用于在 directive 的 compile 方法调用之前进行排序。
值越大越先编译。
如果优先级相同,则执行顺序是不确定的。 -
terminal
终点、boolean
、false
如果设置为true
,则表示当前的priority
将会成为最后一组执行的 directive,即比此 directive 的 priority 更低的 directive 将不会执行。同优先级依然会执行,但是顺序不确定。 -
scope
两种值: - true
将为这个 directive 创建一个新的 scope 。
如果在同一个元素中有多个 directive 需要新的 scope 的话,它还是只会创建一个scope。新的 scope 规则不适用于根模版,因为根模版往往会获得一个新的scope。 - {}
将创建一个新的、独立的 scope ,此 scope 与一般的 scope 的区别在于——它不是通过原型继承于父scope的。
这对于创建可复用的组件是很有帮助的,可以有效的防止读取或者修改父级 scope 的数据。这个独立的 scope 会创建一个拥有一组来源于父 scope 的本地 scope 属性 hash 集合。这些本地 scope 属性对于模版创建值的别名很有帮助。本地的定义是对其来源的一组本地 scope property 的 hash 映射。 -
controller
controller构造函数。controller 会在 pre-linking 步骤之前进行初始化,并允许其他 directive 通过指定名称的 require 进行共享。这将允许 directive 之间相互沟通,增强相互之间的行为。controller默认注入了以下本地对象: -
$scope
- 与当前元素结合的 scope -
$element
- 当前的元素 -
$attrs
- 当前元素的属性对象 -
$transclude
- 一个预先绑定到当前 scope 的转置linking function。(A transclude linking function pre-bound to the correct transclusion scope) -
require
请求另外的 controller ,传入当前 directive 的 linking function中。require 需要传入一个 directive controller 的名称。如果找不到这个名称对应的 controller ,那么将会抛出一个 error 。
名称可以加入以下前缀: -
?
不要抛出异常。这将使得这个依赖变为一个可选项 -
^
允许查找父元素的controller -
restrict
EACM 的子集的字符串,它限制了 directive 为指定的声明方式。如果省略的话,directive 将仅仅允许通过属性声明 -
E
元素名称:<my-directive></my-directive>
-
A
属性名:<div my-directive="exp"></div>
-
C
类名:<div class="my-directive : exp"></div>
-
M
注释:`` transclude
compile
link
-
template
如果 replace 为 true ,则将模版内容替换当前的 html 元素,并将原来元素的属性、class一并转移;
如果 replace 为 false,则将模版元素当作当前元素的子元素处理。 -
templateUrl
与 template 基本一致,但模版通过指定的url进行加载。因为模版加载是异步的,所有 compilation、linking 都会暂停,等待加载完毕后再执行。 -
replace
如果设置为 true ,那么模版将会替换当前元素,而不是作为子元素添加到当前元素中。(为 true 时,模版必须有一个根节点)