前言
在我們創建一個angularJS應用的時候,菜單往往往是不可或缺的元素之一。也許在我們靜態菜單的時候不會發現在指令中操作菜單收縮、折疊展開沒有任何問題,因為我們在操作之前,頁面元素渲染已經完成,所以在指令里面通過element查找目標元素可以成功。但是一旦我們的菜單的數據不是靜態而是通過后臺接口加載動態數據渲染,我們會發現本來在靜態寫好的指令操作,在轉變為動態數據加載之后,怎么也沒法查找到想要的目標元素。
遇到如此問題,開始覺得好奇葩的,當然這也是吐槽一下,還是得好好解決問題的,痛定失痛,決心好好理清思路,分析一下問題原因。首先我們先了解一下AngularJS的生命周期。
AngularJS的生命周期
在AngularJS應用啟動前,它們會以HTML文本的形式保存在文本編輯器中。應用啟動后會進行編譯和鏈接,作用域會同HTML進行綁定,應用可以對用戶在HTML中進行的操作進行實時響應。AngularJS的生命周期主要有兩個主要階段:一個是編譯階段,一個是鏈接階段。
AngularJS生命周期-編譯階段
在編譯階段,AngularJS會遍歷整個HTML文檔并根據JavaScript中的指令定義來處理頁面上聲明的指令。每一個指令模板中可能有另一個指令,另一個指令也有可能會有自己的模板。AngularJS調用HTML文檔根部的指令時,會遍歷其中所有的模板,模板中可能含有模板的指令。如果一個元素已經有一個含有模板的指令,永遠不要對其用另一個指令進行修飾,只有最高優先級的指令中的模板會被編譯。
一旦對指令和其中的子模板進行遍歷或編譯,編譯后的模板會返回一個叫做模板函數的函數。在這個時候的DOM樹還沒有進行數據綁定,此時對DOM樹操作只會有很少的性能開銷,ng-repeat和ng-transclude等內置指令會在這個時候對還未進行數據綁定的DOM進行操作。比如ng-repeat,它會遍歷指定的數組或對象,在數據綁定之前構建對應的DOM結構,然后將新的DOM(編譯后的DOM)傳遞給指令生命周期中的下一階段,鏈接階段。一個指令的DOM一旦編譯完成,就可以立即通過編譯函數對其進行訪問,編譯函數的簽名包含有訪問指令聲明所在的元素(tElements)及該元素對其他屬性(tAttrs)的方法。
compile返回對象或函數,compile()函數負責對模板DOM進行轉換,link()函數負責將作用域和DOM進行轉換。
//...compile: function(tEle,tAttrs,transcludeFn){ var tplEl = angular.element('<div>' +'<h2></h2>'+'</div>'); 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){ //連接函數 };}//...
新聞熱點
疑難解答
圖片精選