angular指令比較晦澀難懂的就是complie和link字段了,何時該用complie?何時該用link?老是很難分別清楚。當理解了指令的真正編譯原理的時候,就會發現這至關的簡單。javascript
ng怎樣處理指令實際上是依賴於它定義時的對象屬性的,你能夠定義一個compile或者一個link函數,或者用pre-link和post-link函數來代替link.。
css
咱們先看一段簡單的代碼:html
html代碼java
<level-one> <level-two> <level-three> Hello </level-three> </level-two> </level-one>js代碼
var app = angular.module('plunker', []); function createDirective(name){ return function(){ return { restrict: 'E', compile: function(tElem, tAttrs){ console.log(name + ': compile => ' + tElem.html()); return { pre: function(scope, iElem, iAttrs){ console.log(name + ': pre link => ' + iElem.html()); }, post: function(scope, iElem, iAttrs){ console.log(name + ': post link => ' + iElem.html()); } } } } } } app.directive('levelOne', createDirective('levelOne')); app.directive('levelTwo', createDirective('levelTwo')); app.directive('levelThree', createDirective('levelThree'));結果:
關於complie和preLink和postLink的調用順序能夠參考個人上一篇博文。安全
在這裏再簡要說明一下,從上面的結果能夠看出,全部的指令都是先compile,而後preLink,而後postLink。節點指令的preLink是在全部子節點指令preLink,postLink以前,因此通常這裏就能夠經過scope給子節點傳遞必定的信息。節點指令的postLink是在全部子節點指令preLink,postLink完畢以後,也就意味着,當父節點指令執行postLink時,子節點postLink已經都完成了,此時子dom樹已經穩定,因此咱們大部分dom操做,訪問子節點都在這個階段。markdown
若是你仔細觀察的話,就會發現上述結果中,傳遞給complie的element參數是最原始的html標誌,變量指向的是template element。一旦運行levelone指令中的compile函數,ng就會遞歸深度遍歷它的dom節點,而後在level-two與level-three上面重複這些操做.。由於complie的element是原始的html,因此能夠在ng建立element實例以及建立scope對象以前改變dom的結構,以便在只有一個template element的狀況下,生成多個element實例,例如ngRepeat。app
由於在complie階段,element仍是原生的html,因此此時的scope是尚未建立的,complie函數不可以訪問scope。在complie完成以後,將建立template element的element實例以及實例的scope。當linking發生時,這個實例element以及scope對象已是可用的了,並被傳遞給preLink函數。因此preLink中的element不是一個原始的html,而是一個element實例,它擁有一個scope。一樣的狀況也在postLink之中。dom
一個元素的pre-link函數可以保證是運行在它全部的子指令的post-link與pre-link運行以前執行的。正如以前所說的通常這裏就能夠經過scope給子節點傳遞必定的信息。當運行包含子指令的指令post-link時,反向的post-link規則能夠保證它的子指令的post-link是已經運行過的,這就是爲何人們都認爲post-link是最安全或者默認的寫業務邏輯的地方.。
函數