生命周期概览
整个流程分为两个阶段:$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>'
}
});
- 首先进入$compile。其中tElement和tAttributes为指令传入的属性。如果指令内部有嵌套的子指令(如ng-repeat),
则会遍历调用所有子指令的compile。在我们的例子里,三个子source template(通过ng-repeat)会被创建,所以compile会调用一共4次。
//一个compile函数API类似
compile: function compile( tElement, tAttributes ) { ... }
- 接下来进入nodeLinkFn阶段(link阶段)。经由$compile返回的link函数被提供一个scope。
首先link函数创建一个子scope(scope:true),或者一个隔离作用域(scope:{...})。接着执行controller函数,传入scope。
//一个controller函数API类似
controller: function controller($scope, $element, $attrs,$transclude ) { ... }
- 接下来进入pre-link阶段,基本上在controller和preLink之间不会执行其他函数。在父级preLink被调用,紧接着会遍历调用子级preLink。
//一个preLink函数API类似
preLink: function preLink(scope, element, attrs,controller ) { ... }
//postLink与preLink API类似
postLink: function postLink(scope, element, attrs,controller ) { ... }
注意当一个
子级preLink函数执行完后会继续执行该子子级的postLink函数,接着再执行下一个子级的preLink与postLink。也就说当父级执行postLink时,其所有子级的link函数都已执行完毕。这意味着子级已经完成:
- 数据绑定
- transclusion已经应用
- scope形成
//这个阶段的DOM结构看起来如下
<my-element>
<div class="ng-binding">
"{{label}}"
<div ng-transclude>
<div class="ng-scope">Inner content</div>
</div>
</div>
</my-element>