angular学习笔记(三十)-指令(7)-compile和link(2)

继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1)

上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序.

看一段三个指令嵌套的代码:

html:

<body>
  <div ng-controller="compileCtrl">
    <level-one>
      <level-two>
        <level-three>
          hello,{{name}}
        </level-three>
      </level-two>
    </level-one>
  </div>
</body>

js:

/*20.8.2 指令-compile和link*/
var appModule = angular.module('dirAppModule',[]);

  appModule.controller('compileCtrl',function($scope){
    $scope.name="code_bunny"
  });


appModule.directive(
'levelOne',function(){ return { restrict:'E', compile:function(tEle,tAttrs,trans){ console.log('compile→'+'levelOne'); return { pre:function(){ console.log('pre→'+'levelOne') }, post:function(){ console.log('post→'+'levelOne') } } } } }); appModule.directive('levelTwo',function(){ return { restrict:'E', compile:function(tEle,tAttrs,trans){ console.log('compile→'+'levelTwo'); return { pre:function(){ console.log('pre→'+'levelTwo') }, post:function(){ console.log('post→'+'levelTwo') } } } } }); appModule.directive('levelThree',function(){ return { restrict:'E', compile:function(tEle,tAttrs,trans){ console.log('compile→'+'levelThree'); return { pre:function(){ console.log('pre→'+'levelThree') }, post:function(){ console.log('post→'+'levelThree') } } } } });

得到结果:

因此,他们的执行顺序如下:

1.从外层到内层执行指令的compile函数

2.compile执行完毕以后,从外层到内层执行指令的pre-link函数

3.pre-link全部执行完以后,从内层到外层执行指令的post-link函数

代码测试地址:http://jsfiddle.net/9hoqvtja/1/

然后我们修改一下js代码如下:

/*20.8.2 指令-compile和link*/

appModule.directive('levelOne',function(){
    return {
        restrict:'E',
        scope:true,
        compile:function(tEle,tAttrs,trans){
            console.log('compile→'+'levelOne'+tEle.html());
            return {
                pre:function(scope,iEle,iAttrs){
                    console.log('pre→'+'levelOne'+iEle.html())
                },
                post:function(scope,iEle,iAttrs){
                    console.log('post→'+'levelOne'+iEle.html())
                }
            }
        }
    }
});
appModule.directive('levelTwo',function(){
    return {
        restrict:'E',
        scope:true,
        compile:function(tEle,tAttrs,trans){
            console.log('compile→'+'levelTwo'+tEle.html());
            return {
                pre:function(scope,iEle,iAttrs){
                    console.log('pre→'+'levelTwo'+iEle.html())
                },
                post:function(scope,iEle,iAttrs){
                    console.log('post→'+'levelTwo'+iEle.html())
                }
            }
        }
    }
});
appModule.directive('levelThree',function(){
    return {
        restrict:'E',
        scope:true,
        compile:function(tEle,tAttrs,trans){
            console.log('compile→'+'levelThree'+tEle.html());
            return {
                pre:function(scope,iEle,iAttrs){
                    console.log('pre→'+'levelThree'+iEle.html())
                },
                post:function(scope,iEle,iAttrs){
                    console.log('post→'+'levelThree'+iEle.html())
                }
            }
        }
    }
});

我们给指令添加scope属性,在打印的过程中加入打印tEle和iEle的内容,结果如下:

可以看到,才compile阶段打印出的元素,是没有class属性的,但是在pre-link和post-link阶段打印出的元素,class属性为ng-scope ng-binding.

原因是:

compile阶段得到的元素是tElement,也就是templateElement,是原始的元素.

link阶段(无论是pre-link还是post-link),得到的是元素是iElement,也就是instanceElement,是经过compile编译后的元素的实例.

那么原始的元素和元素的实例有什么区别呢? 我的理解(不一定对)是:tElement就是最原始的元素,也就会说,页面里写的html是啥,它就是啥.而iElement就经过了angular的编译处理了.他具体处理了一些什么事情,我现在不知道,但是就这个例子,可以看到,它至少处理了'给元素绑定scope作用域','对元素里的数据与模型进行双向绑定',当然他一定还处理了很多其他的事情...这就是为什么compile是没有scope参数的,因为它还没有编译嘛~ 

代码测试地址:http://jsfiddle.net/0kgn110u/1/

总结一下刚才讲的所有知识:

1.compile函数的执行顺序是从父元素向子元素执行.当某个指令的compile被执行时,它的父元素的compile都已经被执行了.它的tEle参数和tAttrs参数,指的的原始的元素和原始元素的属性,原始元素没有经过angular编译.

2.pre-link函数的执行顺序是从父元素向子元素执行.当某个指令的pre-link被执行时,它的父元素和它自己的compile函数,以及它的父元素的pre-link函数都已经被执行了.它的iEle参数和iAttrs参数,指的是经过ng编译的元素.

3.post-link函数的执行顺序是从子元素向父元素执行.当某个指令的post-link被执行时,它的父元素和它自己的compile函数,以及它的子元素的post-link函数都已经被执行了.它的iEle函数和iAttrs参数,指的是,经过ng编译的元素.

参考文献:[译]ng指令中的compile与link函数解析

但是上面说的这一切,当指令中有template(templateUrl)的时候,它compile和link的执行顺序就不是这样的了.下一篇继续讲解这种情况.

原文地址:https://www.cnblogs.com/liulangmao/p/3980256.html