## 第十章 指令詳解
### 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 嵌入鏈接函數會與對應的嵌入作用域進行預綁定。