## 第十章 指令详解
### 10.1 指令定义
在特定DOM上运行的函数。用来扩张元素的功能。
```js
angular.application('myApp', [])
.directive('myDirective', function() {
// 一个指令定义对象
return {
// 通过设置项来定义指令,在这里进行覆写
};
});
```
当AngularJS启动应用时,它会把第一个参数当作一个字符串,并以此字符串为名来注册第二个参数返回的对象。AngularJS编译器会解析主HTML的DOM中的元素、属性、注释和CSS类名中使用了这个名字的地方,并在这些地方引用对应的指令。当它找到某个已知的指令时,就会在页面中插入指令所对应的DOM元素。
```js
angular.module('myApp', [])
.directive('myDirective', function() {
return {
restrict: String,
priority: Number,
terminal: Boolean,
template: String or Template Function:
function(tElement, tAttrs) (...},
templateUrl: String,
replace: Boolean or String,
scope: Boolean or Object,
transclude: Boolean,
controller: String or
function(scope, element, attrs, transclude, otherInjectables) { ...
},
controllerAs: String,
require: String,
link: function(scope, iElement, iAttrs) {
...
},
compile: // 返回一个对象或连接函数,如下所示:
function(tElement, tAttrs, transclude) {
return {
pre: function(scope, iElement, iAttrs, controller) { ... },
post: function(scope, iElement, iAttrs, controller) { ... }
}
// 或者
return function postLink(...) { ... }
}
};
});
```
#### 10.1.1 restrict 声明形式(字符串)
它告诉AngularJS这个指令在DOM中可以何种形式被声明。默认AngularJS认为restrict的值是A,即以属性的形式来进行声明。
* E(元素)`<my-directive></my-directive>`
* C(类名)`<div class="my-directive:expression;"></div>`
* M(注释)`<--directive:my-directive expression-->`
* A(属性,默认值)`<div my-directive="expression"></div>`
#### 10.1.2 priority 优先级(数值型)
指定指令的运行次序。
* 相同优先级指令,先声明先执行;
* 不同优先级指令,数值大的先执行。
#### 10.1.3 terminal (布尔型)
这个参数用来告诉AngularJS停止运行当前元素上比本指令优先级低的指令。但同当前指令优先级相同的指令还是会被执行。
#### 10.1.4 template 模板(字符串或函数)
参数形式
* HTML代码: 必须存在一个 **根** DOM元素
* function(tElement, tAttrs) { }
#### 10.1.5 templateUrl(字符串或函数)
* 一个代表外部HTML文件路径的字符串;
* 一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个外部HTML文件路径的字符串。
#### 10.1.6 replace(布尔型)
false 意味着模板会被当作子元素插入到调用此指令的元素内部.
### 10.2 指令作用域
#### 10.2.1 scope参数(布尔型或对象)
* true 继承作用域
* { } 隔离作用域
### 10.3 绑定策略
AngularJS提供了几种方法能够将指令内部的隔离作用域,同指令外部的作用域进行数据绑定。
**本地作用域属性**:
通过 `@` 符号将本地作用域同 DOM 属性的值进行绑定。 指令内部作用域可以使用外部作用域的变量:`@ (or @attr)`
**双向绑定**:
通过 `=` 可以将本地作用域上的属性同父级作用域上的属性进行双向的数据绑定。
**父级作用域绑定**:
通过 `&` 符号可以对父级作用域进行绑定,以便在其中运行函数。
~~~
<input type="text" ng-model="to"/>
<!-- 调用指令 -->
<div scope-example ng-model="to" on-send="sendMail(email)" from-name="ari@fullstack.io" />
~~~
#### 10.3.1 transclude P102
#### 10.3.2 controller(字符串或函数)
~~~javascript
angular.module('myApp', [])
.directive('myDirective', function() {
restrict: 'A', // 始终需要
controller: 'SomeController'
})
// 应用中其他的地方,可以是同一个文件或被index.html包含的另一个文件
angular.module('myApp')
.controller('SomeController', function($scope, $element, $attrs, $transclude) {
// 控制器逻辑放在这里
});
~~~
~~~
angular.module('myApp',[])
.directive('myDirective', function() {
restrict: 'A',
controller: function($scope, $element, $attrs, $transclude) {
// 控制器逻辑放在这里
}
});
~~~
* $scope 与指令元素相关联的当前作用域。
* $element 当前指令对应的元素。
* $attrs 由当前元素的属性组成的对象。`<div id="aDiv"class="box"></div>` <=> `{ id:"aDiv",class: "box"}`
* $transclude 嵌入链接函数会与对应的嵌入作用域进行预绑定。