angular的生命周期 21

1、编译阶段

第一个阶段是编译阶段。在编译阶段,AngularJS会遍历整个HTML文档并根据JavaScript中的指令定义来处理页面上声明的指令。

一旦对指令和其中的子模板进行遍历或编译,编译后的模板会返回一个叫做模板函数的函数。我们有机会在指令的模板函数被返回前,对编译后的DOM树进行修改。

在这个时间点DOM树还没有进行数据绑定,意味着如果此时对DOM树进行操作只会有很少的性能开销。基于此点, ng-repeat和ng-transclude等内置指令会在这个时候,也就是还未与任何作用域数据进行绑定时对DOM进行操作。

2、compile(对象或函数)

compile选项可以返回一个对象或函数。

compile选项本身并不会被频繁使用,但是link函数则会被经常使用。本质上,当我们设置了link选项,实际上是创建了一个postLink()链接函数,以便compile()函数可以定义链接函数。

通常情况下,如果设置了compile函数,说明我们希望在指令和实时数据被放到DOM中之前进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的。

注:compile和link选项是互斥的。如果同时设置了这两个选项,那么会把compile所返回的函数当作链接函数,而link选项本身则会被忽略。

不要进行DOM事件监听器的注册:这个操作应该在链接函数中完成。

compile: function(tEle, tAttrs, transcludeFn) {

var tplEl = angular.element('

' +'

' +'

');

var h2 = tplEl.find('h2');

h2.attr('type', tAttrs.type);

h2.attr('ng-model', tAttrs.ngModel);

h2.val("hello");

tEle.replaceWith(tplEl);

return function(scope, ele, attrs) {

// 连接函数

};

}

编译函数负责对模板DOM进行转换。

链接函数负责将作用域和DOM进行链接。

3、链接

用link函数创建可以操作DOM的指令。

链接函数是可选的。如果定义了编译函数,它会返回链接函数,因此当两个函数都定义了时,编译函数会重载链接函数。如果我们的指令很简单,并且不需要额外的设置,可以从工厂函数 (回

调函数)返回一个函数来代替对象。如果这样做了,这个函数就是链接函数。

下面两种定义指令的方式在功能上是完全一样的:

angular.module('myApp', [])

.directive('myDirective', function() {

return {

pre: function(tElement, tAttrs, transclude) {

// 在子元素被链接之前执行

// 在这里进行Don转换不安全

// 之后调用'lihk'h函数将无法定位要链接的元素

},

post: function(scope, iElement, iAttrs, controller) {

// 在子元素被链接之后执行

// 如果在这里省略掉编译选项

//在这里执行DOM转换和链接函数一样安全吗

}

};

});

angular.module('myApp', [])

.directive('myDirective', function() {

return {

link: function(scope, ele, attrs) {

return {

pre: function(tElement, tAttrs, transclude) {

// 在子元素被链接之前执行

// 在这里进行Don转换不安全

// 之后调用'lihk'h函数将无法定位要链接的元素

},

post: function(scope, iElement, iAttrs, controller) {

// 在子元素被链接之后执行

// 如果在这里省略掉编译选项

//在这里执行DOM转换和链接函数一样安全吗

}

}

}

});

如果你编写自定义的compile函数,则自定义的link函数无效应为compile会返回一个link函数

下面看一下链接函数中的参数:

scope

指令用来在其内部注册监听器的作用域。

iElement

iElement参数代表实例元素,指使用此指令的元素。在postLink函数中我们应该只操作此元素的子元素,因为子元素已经被链接过了。

iAttrs

iAttrs参数代表实例属性,是一个由定义在元素上的属性组成的标准化列表,可以在所有指令的链接函数间共享。会以javascript对象的形式进行传递。

controller

controller 参 数 指 向 require 选 项 定 义 的 控 制 器 。 如 果 没 有 设 置 require 选 项 , 那 么controller参数的值为undefined。

控制器在所有的指令间共享,因此指令可以将控制器当作通信通道(公共API)。如果设置了多个require,那么这个参数会是一个由控制器实例组成的数组,而不只是一个单独的控制器。

总结:

(1)compile函数的作用就是对指令的模板函数进行转换。

(2)link函数是在模型和视图之间建立关联,包括在元素上注册监听事件。

(3)scope在连接阶段才被绑定到元素上,所以在compile阶段操作scope回报错误。

(4)一般情况下,我们只写link函数就够了。

(5)请注意,如果你编写自定义的compile函数,则自定义的link函数无效应为compile会返回一个link函数

推荐阅读更多精彩内容