智商捉急,就到這裡~
接下來聊聊angular的指令機制。angular通過指令的方式實作了HTML的擴充,增強後的HTML就好比是究極進化後的暴龍獸,不僅長相煥然一新,同時也獲得了很多強大的技能。更厲害的是,你還可以自定義指令,這就意味着HTML标簽的範圍可以擴充到無窮大,ng賦予了你造物主的能力。作為angular的精華之一,指令相關的知識也很多,本篇開始探索自定義指令的方方面面。為了不讓我的篇幅再拉那麼長,我識趣的在标題後面加了(上),你懂的。
在開始自定義指令之前,我們有必要了解一下指令在架構中的執行流程。這部分内容我沒有自己研究,隻是照搬了别人的說法:
浏覽器得到 HTML 字元串内容,解析得到 DOM 結構。
ng 引入,把 DOM 結構扔給 $compile 函數處理:
① 找出 DOM 結構中有變量占位符
② 比對找出 DOM 中包含的所有指令引用
③ 把指令關聯到 DOM
④ 關聯到 DOM 的多個指令按權重排列
⑤ 執行指令中的 compile 函數(改變 DOM 結構,傳回 link 函數)
⑥ 得到的所有 link 函數組成一個清單作為 $compile 函數的傳回
3. 執行 link 函數(連接配接模闆的 scope)。
這裡注意差別一下$compile和compile,前者是ng内部的編譯服務,後者是指令中的編譯函數,兩者發揮作用的範圍不同。compile和link函數息息相關又有所差別,這個在後面會講。了解執行流程對後面的了解會有幫助。
在這裡我小小的多嘴一下,有些人可能會問,angular不就是一個js架構嗎,怎麼還能跟編譯扯上呢,又不是像C++那樣的進階語言。其實此編譯非彼編譯,ng編譯的工作是解析指令啦,綁定監聽器啦,替換模闆中的變量啦這些。因為工作方式很像進階語言編輯中的遞歸、堆棧過程,是以起名為編譯,不要疑惑。
指令的幾種使用方式如下:
作為标簽:<my-dir></my-dir>
作為屬性:<span my-dir="exp"></span>
作為注釋:<!-- directive: my-dir exp -->
作為類名:<span class="my-dir: exp;"></span>
其實常用的就是作為标簽和屬性,下面兩種用法目前還沒見過,姑且留個印象。我們自定義的指令就是要支援這樣的用法。
關于自定義指令的命名,你可以随便怎麼起名字都行,官方是推薦用[命名空間-指令名稱]這樣的方式,像ng-controller。不過你可千萬不要用ng-字首了,防止與系統自帶的指令重名。另外一個需知道的地方,指令命名時用駝峰規則,使用時用-分割各單詞。如:定義myDirective,使用時像這樣:<my-directive>。
下面是定義一個标準指令的示例,可配置的參數包括以下部分:


看上去好複雜的樣子啊~定義一個指令需要這麼多步驟嘛?當然不是,你可以根據自己的需要來選擇使用哪些參數。事實上priority和compile用的比較少,template和templateUrl又是互斥的,兩者選其一即可。是以不必緊張,接下來分别學習一下這些參數,我将先從一個簡單的例子開始。為了易于了解和我以後翻看的時候還能看明白,我盡量使用有語義的命名,而不是像test1,test2這樣。
例子的代碼如下:


然後在頁面中,我們就可以使用這個名為sayHello的指令了,它的作用就是輸出一個hello單詞。像這樣使用:
這樣頁面就會顯示出hello了,看一下生成的代碼:
稍稍解釋一下我們用到的兩個參數,restirct用來指定指令的使用類型,其取值及含義如下:
取值
含義
使用示例
E
标簽
<my-menu title=Products></my-menu>
A
屬性
<div my-menu=Products></div>
C
類
<div class="my-menu":Products></div>
M
注釋
<!--directive:my-menu Products-->
預設值是A。也可以使用這些值的組合,如EA,EC等等。我們這裡指定為E,那麼它就可以像标簽一樣使用了。如果指定為A,我們使用起來應該像這樣:
<div say-hello></div>
從生成的代碼中,你也看到了template的作用,它就是描述你的指令長什麼樣子,這部分内容将出現在頁面中,即該指令所在的模闆中,既然是模闆中,template的内容中也可以使用ng-modle等其他指令,就像在模闆中使用一樣。
在上面生成的代碼中,我們看到了<div>hello</div>外面還包着一層<say-hello>标簽,如果我們不想要這一層多餘的東西了,replace就派上用場了,在配置中将replace指派為true,将得到如下結構:
replace的作用正如其名,将指令标簽替換為了temple中定義的内容。不寫的話預設為false。
上面的template未免也太簡單了,如果你的模闆HTML較複雜,如自定義一個ui元件指令,難道要拼接老長的字元串?當然不需要,此時隻需用templateUrl便可解決問題。你可以将指令的模闆單獨命名為一個html檔案,然後在指令定義中使用templateUrl指定好檔案的路徑即可,如:
系統會自動發一個http請求來擷取到對應的模闆内容。是不是很友善呢,你不用糾結于拼接字元串的煩惱了。如果你是一個追求完美的有考慮性能的工程師,可能會發問:那這樣的話豈不是要犧牲一個http請求?
這也不用擔心,因為ng的模闆還可以用另外一種方式定義,那就是使用<script>标簽。使用起來如下:
你可以把這段代碼寫在頁面頭部,這樣就不必去請求它了。在實際項目中,你也可以将所有的模闆内容集中在一個檔案中,隻加載一次,然後根據id來取用。
接下來我們來看另一個比較有用的配置:transclude,定義是否将目前元素的内容轉移到模闆中。看解釋有點抽象,不過親手試試就很清楚了,看下面的代碼:


指定了transclude為true,并且template修改了一下,加了一個<b>标簽,并在上面使用了ng-transclude指令,用來告訴指令把内容轉移到的位置。那我們要轉移的内容是什麼呢?請看使用指令時的變化:
<say-hello>美女</say-hello>
内容是什麼你也看到了哈~在運作的時候,美女将會被轉移到<b>标簽中,原來此配置的作用就是——乾坤大挪移!看效果:
這個還是很有用的,因為你定義的指令不可能老是那麼簡單,隻有一個空标簽。當你需要對指令中的内容進行處理時,此參數便大有可用。
看前面寫的兩篇,感覺篇幅太長了,可能會有人耐不住性子看完,故本篇先介紹幾個比較簡單的參數,先拿軟的來捏一捏,更複雜的用法還在後頭。我們将真正用一下自定義指令,起碼也搞個像樣的ui元件出來,這樣才算是學會了。
今天爬香山回來,累的夠嗆,時辰不早,收工睡覺~
本文轉自呂大豹部落格園部落格,原文連結:http://www.cnblogs.com/lvdabao/p/3391634.html,如需轉載請自行聯系原作者