生命周期概覽
整個(gè)流程分為兩個(gè)階段:$compile 和 nodeLinkFn
//總體流程
// The compile phase
parent (compile)
..first-child (compile)
..second-child (compile)
// The link phase
parent (controller)
parent (pre-link)
..first-child (controller)
..first-child (pre-link)
..first-child (post-link)
..second-child (controller)
..second-child (pre-link)
..second-child (post-link)
parent (post-link)
//例子
<div ng-repeat="i in [0,1,2]">
<my-element>
<div>Inner content</div>
</my-element>
</div>
//指令如下
myApp.directive( 'myElement', function() {
return {
restrict: 'EA',
transclude: true,
template: '<div>{{label}}<div ng-transclude></div></div>'
}
});
- 首先進(jìn)入$compile。其中tElement和tAttributes為指令傳入的屬性。如果指令內(nèi)部有嵌套的子指令(如ng-repeat),
則會(huì)遍歷調(diào)用所有子指令的compile。在我們的例子里,三個(gè)子source template(通過ng-repeat)會(huì)被創(chuàng)建,所以compile會(huì)調(diào)用一共4次。
//一個(gè)compile函數(shù)API類似
compile: function compile( tElement, tAttributes ) { ... }
- 接下來進(jìn)入nodeLinkFn階段(link階段)。經(jīng)由$compile返回的link函數(shù)被提供一個(gè)scope。
首先link函數(shù)創(chuàng)建一個(gè)子scope(scope:true),或者一個(gè)隔離作用域(scope:{...})。接著執(zhí)行controller函數(shù),傳入scope。
//一個(gè)controller函數(shù)API類似
controller: function controller($scope, $element, $attrs,$transclude ) { ... }
- 接下來進(jìn)入pre-link階段,基本上在controller和preLink之間不會(huì)執(zhí)行其他函數(shù)。在父級(jí)preLink被調(diào)用,緊接著會(huì)遍歷調(diào)用子級(jí)preLink。
//一個(gè)preLink函數(shù)API類似
preLink: function preLink(scope, element, attrs,controller ) { ... }
//postLink與preLink API類似
postLink: function postLink(scope, element, attrs,controller ) { ... }
注意當(dāng)一個(gè)
子級(jí)preLink函數(shù)執(zhí)行完后會(huì)繼續(xù)執(zhí)行該子子級(jí)的postLink函數(shù),接著再執(zhí)行下一個(gè)子級(jí)的preLink與postLink。也就說當(dāng)父級(jí)執(zhí)行postLink時(shí),其所有子級(jí)的link函數(shù)都已執(zhí)行完畢。這意味著子級(jí)已經(jīng)完成:
- 數(shù)據(jù)綁定
- transclusion已經(jīng)應(yīng)用
- scope形成
//這個(gè)階段的DOM結(jié)構(gòu)看起來如下
<my-element>
<div class="ng-binding">
"{{label}}"
<div ng-transclude>
<div class="ng-scope">Inner content</div>
</div>
</div>
</my-element>