刚开始学习 AngularJS Directive 时,总是不太能搞明白 compile 和 link 两个属性的含义和区别。最近写的多一些,读的资料也多了一些,渐渐有了一些理解,简单记录下来:
compile 属性是一个函数。该函数会针对每一个 directive 的实例执行一次,在 compile 阶段:
- 不能访问 scope
- 元素还没有被插入 document
- 可以修改 template,最终结果会被 angular 缓存
link 属性可以有两种配置方式。 link 属性可以被设置为一个对象,包含 pre, post 两个属性,分别对应一个函数(preLink, postLink)。preList,postLink 的区别在于执行顺序。preLink 是自顶向下的,先父节点,后子节点,postLink 正好相反。
.directive{
return {
link: {
pre: function preLink(){
...
},
post: function postLink() {
...
}
}
}
}
link 属性也可以被直接设置为一个函数,则默认相当于设置了 postLink 函数。
.directive{
return {
link: function link(){
...
}
}
}
等于
.directive{
return {
link: {
post: function post() {
...
}
}
}
}
由此可见,如果直接将 link 属性设置为一个函数,则 link 阶段的执行顺序是自底向上的。
link 阶段会针对每一个被 RENDERED 的 directive 实例执行一次。此阶段:
- 可以访问 scope(因为 controller 已经初始化完成)
- 元素已经被插入 document 中
- 不可以修改 template(angular 会直接使用之前缓存的内容)
如果定义了 compile 属性则 link 属性会被忽略。
如果你想同时使用 compile 方法和 link 方法,那么 compile 方法的返回值需要是一个函数,这个函数会被用作 link 方法。
对于嵌套 directive 的初始化流程中 controller,compile,link 的执行顺序。可以参考下面这个 jsFiddle:
最后是自己的一些感受:
- 如果你想通过程序修改 directive 的 template,那么你需要 compile 方法。
- 如果你想从 scope 中获取数据或者 watch 数据变化并相应的更新 DOM,那么你需要在 link 方法。
- 绝大多数 directive 是用不到 compile 方法的。无谓的引入 compile 方法只会额外增加代码的复杂性。
另外附上几个链接,供有兴趣的朋友阅读: