Angular 1.x 框架原理

指令生命週期

compile階段

  對dom進行編譯,首先(若是有的話)對template進行應用(這個過程只執行一次)。而後把當前指令(內部的指令還沒被渲染)傳遞給iElement,接着執行compile(這個過程執行屢次)。多個指令實例只會執行一次compile,因此只要咱們在compile中對iElemet進行修改,雖然只執行了一次,卻做用到了全部指令實例上。由於這個時候dom尚未進行做用域數據關聯,因此對iElement進行大量的dom修改是很高效率的。html

  若是定義了compile函數,則DDO中的link會失效,因此若是要用到compile和link,只能在compile中返回link函數瀏覽器

例子:app

<dx>
    這是內層
</dx>
<dx a="3">
    這是內層
</dx>
</body>
<script>
    var app = angular.module('app',[]);
    app.directive('dx',function(){
        return {
            compile:function(tElement,tAttrs,transclude){
                tElement[0].innerHTML = 'qweqweqwe'
                return function(scope,ele,attr){
                    if(attr.a == 3){
                        ele[0].innerHTML = 789;
                    }
                }
            }
        }
    });
</script>

運行結果:qweqweqwe 789框架

Link階段

  創建模型與視圖之間的關係。 Postlink在link階段結束時執行,,link階段會鏈接scope,因此咱們才能夠在postlink中使用scope。Link階段會把以前指令compile的結果應用上去,這裏能夠理解爲,一個指令只有一個編譯結果,在link階段卻被多個指令實例複製拿去用了。因此在link中對ele的修改,只會修改到本身的,而不會影響其餘指令實例dom

Link和controller對比

二者均可獲取到當前的做用域;函數

通常來講,controller裏通常放業務邏輯代碼,業務邏輯函數綁定到controller上;而link放監聽事件如watcher等。其實link中也能夠放邏輯代碼,但儘可能不要這麼作,由於很容易形成污染【如繼承了這個scope的子scope均可以訪問到這些變量和方法,容易形成意想不到的後果】。對於父子指令之間須要溝通協做時,通常是用controller來通訊【指令的require能夠獲取controller】或者把通訊的代碼抽取成一個服務,父子指令經過這個服務來通訊。post

ps:指令內部使用有名控制器,就會在做用域上建立一個對應的屬性,能夠直接在視圖中訪問了控制器了,如:ui

<body ng-app="app">
    <div xx>
        {{myController.data}}
    </div>
</body>
<script>
    var app = angular.module('app',[]);
    app.directive('xx',function(){
        return {
            controllerAs:"myController",
            controller:function(){
                this.data = 123;
            }
        }
    });
</script>

執行次序

all compile,由外向裏 》 all controller由外向裏 》 all prelink外向裏 》所有postlink裏向外this

響應式原理:髒檢測

  當用戶與瀏覽器進行了交互【點擊、輸入等】,瀏覽器會執行響應的回調函數。Angular拓展了瀏覽器的這個過程,當發生交互時(或者$setTimeout等),瀏覽器會通知angular框架,進入angular context執行環境,開始執行digest循環。【或者能夠認爲進入angular context,就等同於digest執行】spa

   這也就是爲何在ngClick中觸發digest,會報錯。由於digest循環不能嵌套,執行ngClick的時候、digest沒結束,又再次手動觸發digest的話,就出現嵌套、則報錯。

  在digest循環中執行每一個watch【執行表達式】,查看上一次的值跟這一次執行的值是否發生了變化、發生了變化就調用watch的回調函數,而後從新執行digest,直到執行的每一個watch表達式的值都沒發生變化爲止。{{xx}}會建立一個xx表達式的watch,repeate會建立 1 + n * m 個watch【1:repeat數據源、n循環次數、m循環中的{{item.xx}}】。Digest循環上限重複運算10次,超過則報錯。

報錯的例子【不穩定的模型】:

<span>{{random()}}</span>

// random函數定義以下:
$scope.random = Math.random;

以上的random函數會建立一個watch,可是每次執行watch表達式運算出來的結果都是和上次的不一致,則又從新執行digest,循環往復超過10次,報錯

等循環結束,全部model都穩定了,才批量地更新UI

這裏補充一個工做原理:http://www.cnblogs.com/penghongwei/p/3444601.html

相關文章
相關標籤/搜索