angular directive

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 中以一个元素使用,如下
其中 templaterestrictlink 都是指令配置属性,还有其他的属性,我们对其逐一的解释,属性名称下的第一行分别是属性名称、属性类型、默认值。

  • multiElement
    多元素、booleanfalse
    当此属性设置为 true 时,HTML 编译器将收集在 directive-name-startdirective-name-end 两个属性之间的 DOM 节点,并将它们组一起作为指令元素。
    建议将此功能应用于行为不严格的指令(如 ngclick),和
    不处理或更换子节点(如 nginclude)。
  • priority
    优先级、number0
    当有多个 directive 定义在同一个 DOM 元素上时,有时需要明确他们的执行顺序。
    这个属性用于在 directive 的 compile 方法调用之前进行排序。
    值越大越先编译。
    如果优先级相同,则执行顺序是不确定的。
  • terminal
    终点、booleanfalse
    如果设置为 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 时,模版必须有一个根节点

推荐阅读更多精彩内容