angular學習筆記(三十)-指令(7)-compile和link(2)

詩&遠方發表於2014-09-19

繼續上一篇: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的執行順序就不是這樣的了.下一篇繼續講解這種情況.

相關文章