在開發 AngularJS 的時候,使用 Angular 表達式是一件很過癮的事,因為所有表達式的內容,都會因為 AngularJS 自動繫結的關係,所有 model 的變化,都會自動反映到頁面上 ( View )。不過,當 AngularJS 正在初始化的時候,由於尚未開始運作,且網頁又已經被載入到瀏覽器中,因此使用者很有可能會看到 Angular 表達式出現在頁面上,而這就不是一件有趣的事了!今天我要來講解幾個 Angular 表達式的使用技巧,以及使用 ngBind 指令 (directive) 的時機。
用【前端工程的極致精品: AngularJS 開發框架介紹】文章範例來說明:http://jsbin.com/ocexek/2/edit
以下是 HTML 部分:

以下是 AngularJS 尚未針對 DOM 編譯完成的畫面,當你的 AnguarJS 應用程式寫的越來越大、越來越複雜,使用者越有機會看到如下圖的畫面:

http://jsbin.com/ocexek/4/edit
此時,就是使用 ngBind 的時候,因為使用了 ngBind 會搭配一個 HTML 標籤使用,其 Angular 表達式會被寫在 ng-bind 屬性裡,因此當頁面被載入時,並不會顯示任何內容!
以上圖為例,我們修改如下:


http://jsbin.com/ocexek/8/edit
當然,另一種實用技巧就是輸入「預設值」,也就是當 AngularJS 尚未完成編譯時應該出現的內容:


在實務上,其實還有一個可能的需求,就是希望能透過 Angular 表達式輸出原始的 HTML 內容,在預設的情況下,使用 {{ 表達式 }} 是無法輸出原始 HTML 的,也就是說,所有透過預設 Angular 表達式輸出的內容,一定會被 HTMLEncode 過。
先用以下語法為例,在 AnguarJS 是完全無法編譯的:


http://jsbin.com/ocexek/9/edit
如果變數內容改從 Controller 傳入,那麼輸出可以正常執行,不過所有 HTML 標籤都會編碼後輸出,這是為了保護你的網頁不易遭受 XSS 攻擊。



http://jsbin.com/ocexek/11/edit
為了讓 model 裡的 HTML 能夠原封不動的輸出,你可以使用 ngBindHtmlUnsafe 指令,如下範例:



http://jsbin.com/ocexek/13/edit
最後,還有一個 ngBindTemplate 指令,用法與 ngBind 非常類似,差別僅在於 ngBindTemplate 指令是一個「範本」,在 ng-bind-template 屬性裡,可以輸入多個包含 {{ }} 在內的 Angular 表達式,其實就是把原本顯示在 HTML 裡面的 Angular 表達式改成用 ngBindTemplate 指令輸出而已,差別僅在於 AngularJS 在編譯網頁的過程中,會不會顯示 Angular 表達式而已。所以如果你想要隱藏 Angular 表達式的話,使用 ngBindTemplate 指令是最方便的。
如下範例:



最後,再推薦一個 ngCloak 指令,這個指令可以套用在任意標籤上,如下語法:
<div ng-cloak class="ng-cloak">
{{ 'hello IE7' }}
</div>
套用這個 ngCloak 指令,最主要的目的就是讓 AngularJS 在編譯的過程中,不讓某些標籤顯示內容,所以也是用來解決 AngularJS 在針對 DOM 編譯完成前,瀏覽器會顯示 Angular 表達式的問題。
不過,套用前最好先載入以下 CSS 語法,才能確保跨瀏覽器都能正常運作:
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
請注意: 上述語法與 AngularJS 官網文件 (ngCloak directive) 寫的有點不太一樣,主要是在樣式加上了
!important 修飾子,確保這些元素一定會被隱藏。否則如果你套用了某些 CSS 框架,影響了上述樣式的運作也說不定。(例如這個問題)
相關連結