﻿# 關於 AngularJS 表達式與 ngBind 指令 (directive) 的使用技巧

在開發 AngularJS 的時候，使用 Angular 表達式是一件很過癮的事，因為所有表達式的內容，都會因為 AngularJS 自動繫結的關係，所有 model 的變化，都會自動反映到頁面上 ( View )。不過，當 AngularJS 正在初始化的時候，由於尚未開始運作，且網頁又已經被載入到瀏覽器中，因此使用者很有可能會看到 Angular 表達式出現在頁面上，而這就不是一件有趣的事了！今天我要來講解幾個 Angular 表達式的使用技巧，以及使用 ngBind 指令 (directive) 的時機。

用【[前端工程的極致精品： AngularJS 開發框架介紹](/post/2013/04/23/Front-end-Engineering-Fineart-An-Introduction-to-AngularJS)】文章範例來說明：[http://jsbin.com/ocexek/2/edit](http://jsbin.com/ocexek/2/edit "http://jsbin.com/ocexek/2/edit")

以下是 HTML 部分：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/8e972424c8212abc359d-image_2074.png)

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

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/93c26cc355c3ccd5066a-image_2075.png "image")

[http://jsbin.com/ocexek/4/edit](http://jsbin.com/ocexek/4/edit)

此時，就是使用 [ngBind](http://docs.angularjs.org/api/ng.directive:ngBind) 的時候，因為使用了 [ngBind](http://docs.angularjs.org/api/ng.directive:ngBind) 會搭配一個 HTML 標籤使用，其 Angular 表達式會被寫在 ng-bind 屬性裡，因此當頁面被載入時，並不會顯示任何內容！

以上圖為例，我們修改如下：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/e9785df3f322257b0c44-image_2076.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/7d33d17e201270c46ae9-image_2077.png)

[http://jsbin.com/ocexek/8/edit](http://jsbin.com/ocexek/8/edit)

當然，另一種實用技巧就是輸入「**預設值**」，也就是當 AngularJS 尚未完成編譯時應該出現的內容：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/8678439c565243ecb7a7-image_2078.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/abe1b6b0014209277b5d-image_2079.png)

在實務上，其實還有一個可能的需求，就是希望能透過 Angular 表達式輸出原始的 HTML 內容，在預設的情況下，使用 **{{ 表達式 }}** 是無法輸出原始 HTML 的，也就是說，所有透過預設 Angular 表達式輸出的內容，一定會被 HTMLEncode 過。

先用以下語法為例，在 AnguarJS 是完全無法編譯的：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/4a8f848b7144f9c061f9-image_2080.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/049120dfca0ef7d0e90c-image_2081.png)

[http://jsbin.com/ocexek/9/edit](http://jsbin.com/ocexek/9/edit)

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

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/0dcbe0fe43a949f0c473-image_2082.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/83ff6d9eb937b15dad36-image_2083.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/e8e7998baade925ab080-image_2084.png)

[http://jsbin.com/ocexek/11/edit](http://jsbin.com/ocexek/11/edit)

為了讓 model 裡的 HTML 能夠原封不動的輸出，你可以使用 [ngBindHtmlUnsafe](http://docs.angularjs.org/api/ng.directive:ngBindHtmlUnsafe) 指令，如下範例：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3e553399c4946a4462af-image_2085.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/dfbcbe5bf772a3c6a1ce-image_2086.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/549ca6c4f42bc5538583-image_2087.png)

[http://jsbin.com/ocexek/13/edit](http://jsbin.com/ocexek/13/edit)

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

如下範例：

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a33a76be14751a836ebf-image_2088.png "image")

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/b6bc704c70c30aa54c02-image_2089.png "image")

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6356d9bcb873ff176beb-image_2090.png "image")

最後，再推薦一個 [ngCloak](http://docs.angularjs.org/api/ng.directive:ngCloak) 指令，這個指令可以套用在任意標籤上，如下語法：

```
<div ng-cloak class="ng-cloak">
  {{ 'hello IE7' }}
</div>
```

套用這個 [ngCloak](http://docs.angularjs.org/api/ng.directive: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](http://docs.angularjs.org/api/ng.directive:ngCloak)) 寫的有點不太一樣，主要是在樣式加上了  
!important 修飾子，確保這些元素一定會被隱藏。否則如果你套用了某些 CSS 框架，影響了上述樣式的運作也說不定。([例如這個問題](http://stackoverflow.com/questions/11249768/angularjs-ng-cloak-ng-show-elements-blink/13276214#13276214))

**相關連結**

-   [ngBind (directive in module ng )](http://docs.angularjs.org/api/ng.directive:ngBind)
-   [ngBindHtmlUnsafe (directive in module ng )](http://docs.angularjs.org/api/ng.directive:ngBindHtmlUnsafe)
-   [ngBindTemplate (directive in module ng )](http://docs.angularjs.org/api/ng.directive:ngBindTemplate)
-   [ngCloak (directive in module ng )](http://docs.angularjs.org/api/ng.directive:ngCloak)
