原文再續,書接上回。。。依舊參考http://code.angularjs.org/1.0.2/docs/guide/compiler
一、總括
Angular的HTML compiler允許開發人員自訂新的HTML文法。compiler允許我們對任意HTML元素或屬性,甚至是新的HTML標籤、屬性(如<beautiful girl=”cf”></beautiful >)附加行為。Angular將這些附加行為稱為directives。
HTML有很多專門格式化靜態文檔的預定義HTML樣式結構(可以告訴瀏覽器如何顯示標記的內容)。假設某東東需要被置中,而我們不需要教瀏覽器如何去做(此處省略N字)。我們只需要簡單地對需要置中的標籤加入align=”center”即可。這就是聲明式語言(declarative language)的牛X之處。
但是聲明式語言也有它的局限性,即你不能告訴瀏覽器如何處理在預定義範圍外的文法。例如,我們不能很簡單地告訴瀏覽器如何讓文本在瀏覽器的1/3處對齊。所以,我們正需要一個讓瀏覽器與時俱進,學學新文法的途徑。
Angular預先綁定了一些對構建應用有協助的directives。我們也可以自己建立屬於自己應用的獨特的directives。這些directive擴充將成為我們自己的應用的“特定領域語言”(Domain Specific Language)。
這些編譯將僅僅發生在瀏覽器端,無須服務端或者先行編譯步驟。
二、Compiler
Compiler作為Angular的一個服務(Service),負責遍曆DOM結構,尋找屬性。編譯過程分成兩個階段:
1. 編譯(Compile):遍曆DOM節點樹,收集所有directives。返回結果是一個連結函數(linking function)。
2. 連結(Link):將directives綁定到一個範圍(scope)中,建立一個實況視圖(live view)。在scope中的任何改變,將會在視圖中得到體現(更新視圖);任何使用者對模版的活動(改變),將會體現在scope model中(雙向繫結)。這使得scope model能夠反映正確的值。
一些directives,諸如ng-repeat,會為每一個在集合(collection)中的元素複製一次特定的元素(組合)。編譯和連結兩個階段,使效能得以提升。因為複製出來的模版(template)只需要編譯一次,然後為每一個集合中的元素進行一次連結(類似模版緩衝)。
三、Directive
Directive是一個行為,在編譯過程中遇到特定的HTML結構時,它會被觸發。Directives可以放置在元素的name、attribute、class甚至注釋中。以下是幾種引用ng-bind(一個內建directive)的方法:
<span ng-bind="exp"></span><span class="ng-bind: exp;"></span><ng-bind></ng-bind><!-- directive: ng-bind exp -->
Directive只是一個當編譯器在DOM中遇到時會執行的一個函數(function)。directive API文檔中有詳細講解如何建立一個directive。
下面是一個範例,可以讓一個元素跟你的滑鼠玩躲貓貓……
<!DOCTYPE html><html lang="zh-cn" ng-app="HideAnkSeek"><head> <meta charset="UTF-8"> <title>躲貓貓</title> <style type="text/css"> .ng-cloak { display: none; } </style></head><body><span class="ng-cloak" wildcat>一碰我就跑~~來點我啊~~</span><script src="../angular-1.0.1.js" type="text/javascript"></script><script type="text/javascript"> angular.module("HideAnkSeek", []).directive("wildcat", function ($document) { var maxLeft = 400,maxTop = 300; var msg = ["我閃~~", "抓我呀~~~", "雅蠛蝶~~", "噢耶~~", "你真遜~!","就差那麼一點點了!","繼續吧~~總有一天我會累的"]; return function (scope, element, attr) { element.css({ "position":"absolute", "border":"1px solid green" }); element.bind("mouseenter", function (event) { element.css({ "left":parseInt(Math.random() * 10000 % maxLeft) + "px", "top":parseInt(Math.random() * 10000 % maxTop) + "px" }).text(msg[parseInt(Math.random() * 10000 % msg.length)]); }).bind("click",function (event) { element.text("噢My Lady Gaga。。。被你逮到了。。。"); element.unbind("mouseenter"); }); }; });</script></body></html>
在任意元素中添加“wildcat”這個屬性,將會使該元素擁有新的行為。就這樣,我們教會了瀏覽器如何處理會躲貓貓的元素(放心,你不是在某個房間,你不會掛的-_-!)。我們通過這一途徑擴充了瀏覽器的“詞彙量”。對於任意一個熟悉HTML規則的人,這算是一個比較自然的方式。
現在已經夜深了,明天繼續。。。廣告之後見
===================華麗的分割線=======================
四、理解視圖(View)
外面有許多模版系統,它們通常都通過模版字串與資料進行串連,產生最終的HTML字串,並將結果通過innerHTML 屬性寫入某元素裡。
這意味著任何資料發生改變時,都需要重新將資料、模版合并成字串,然後當作innerHTML寫回對應元素中。這裡存在一些問題:(這裡直譯實在沒法懂..唯有YY)假設有這麼一個情境,模版裡包含輸入框。使用者對在輸入框進行輸入,模版同步更新。普通模版通過innerHTML、字串與資料連線的方式更新視圖,這樣會打斷使用者的輸入,體驗不好。
Angular是與眾不同的。Angular編譯器(compiler)通過directives處理DOM,而不是通過處理字串模版。處理結果是一個與scope model組合并產生即時模版的連結函數(linking function)。視圖與scope model的綁定對我們來說是透明的。開發人員無須為更新視圖、model做任何動作。而且,因為沒有使用innerHTML更新視圖模版,所以使用者輸入不會被打斷。此外,angular directives不僅可以綁定文本值,而且還可以是擁有行為的結構(behavioral constructs)。
Angular的這個處理方式,產生了一個穩定的DOM。這意味著在DOM元素的生命週期裡,一直與某model的執行個體綁定著,這個關係不會發生改變。這也意味著代碼可以保持對某DOM對象的引用,對其註冊事件函數,並且這個引用不會被模版資料合併所銷毀。