本節書摘來自異步社群《angularjs進階程式設計》一書中的第2章,第2.2節,作者:【美】adam freeman(弗裡曼)著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
對于要建立的基本功能來說,todo.html檔案中的靜态html目前僅作為占位符使用。使用者應該能看到待辦事項的清單,勾選掉已完成的事項,并建立新事項。在下面各節中,我打算将angularjs加進來,并應用一些基本特性來為我的待辦事項應用賦予生命。簡單起見,假定隻有一個使用者,并且不用考慮保留應用程式中的資料狀态。
2.2.1 将angularjs應用到html檔案
将angularjs加入到html檔案中是挺簡單的,隻需簡單增加一個script元素來引入angular.js檔案,建立一個angularjs子產品,并對html元素應用一個屬性即可,如清單2-2所示。
清單2-2 在todo.html檔案中建立和使用一個angularjs子產品

angularjs應用由一個或多個子產品組成。子產品是由調用angular.module方法而建立的,如下:
我将在第9章和第18章中适當地介紹子產品,但是你可以從清單2-2中看到我是如何為該執行個體建立并使用一個子產品的。傳給angular.module方法的參數是要建立的子產品名以及一個由所需要的其他子產品構成的數組。我建立了一個名為todoapp的子產品,遵循了那個讓人有點困惑的将app附加到子產品名稱後面的慣用法,并通過将空數組傳給第二個參數來告訴angularjs不再需要其他子產品。(某些angularjs特性在其他不同的子產品中可用,在第18章中還将示範如何建立自己的子產品。)
我通過ng-app屬性告訴angularjs如何使用這個子產品。angularjs通過增加新元素、屬性、css類和特殊注釋(雖然鮮有使用)的方法來擴充html,完成工作。angularjs庫動态地編譯一個文檔中的html,以定位和處理這些附加品,并建立應用程式。你可以使用javascript代碼對内置功能進行補充,定制應用程式的行為,并定義自己向html的附加品。
angularjs對html的最重要的附加品是ng-app屬性,該屬性指定了清單中的html元素包含一個應當被angularjs編譯和處理的子產品。當angularjs是唯一被使用的javascript架構時,慣例是對html元素使用ng-app屬性,就像我在清單2-2中所做的那樣。如果你在将angularjs與其他技術如jquery混用,你可以通過将ng-app屬性使用到文檔裡的某個元素來縮小angularjs應用的邊界。
2.2.2 建立資料模型
angularjs支援模型-視圖-控制器(mvc)模式,在第3章中我将加以介紹。簡而言之,遵循mvc模式需要你将應用程式分成三部分不同的區域:程式中的資料(模型)、對資料進行操作的邏輯(控制器),以及顯示資料的邏輯(視圖)。
在我的待辦事項程式中的資料現在分布在各個html元素之間。使用者名包含在header中,如下:
待辦事項項目的細節包含在表格中的td元素裡,如下:
我的第一個任務就是将所有資料放到一起,并将資料從html元素中分離出來,以便建立一個模型。從對使用者的表現形式中分離資料是mvc模式的關鍵點之一,正如我在第3章中将解釋的。因為angularjs程式存在于浏覽器中,我需要使用一個script元素中的javascript來定義我的資料模型,如清單2-3所示。
清單2-3 在todo.html檔案中建立一個資料模型
我定義了一個名為model的javascript對象,具有與分布在各個html元素中的資料相對應的屬性。user屬性定義了使用者名,items屬性定義了一個對象數組,描述了各個待辦事項。
通常在定義一個模型時,不需要同時定義mvc模式的其他部分,但是我想示範如何搭建這個簡單的angularjs程式,是以也同時定義了其他部分。在圖2-2中可以看到這一修改帶來的變化。
2.2.3 建立控制器
控制器定義了用于支援視圖的業務邏輯,盡管業務邏輯這一術語并不是很有用。描述控制器的最好的方式是解釋清楚它不應包含什麼樣的邏輯,以及控制器中剩下了哪些邏輯。
處理存儲或讀取資料的邏輯是模型的一部分。處理将資料格式化并顯示給使用者的邏輯是視圖的一部分。控制器位于模型和視圖之間并連接配接它們。控制器對使用者互動做出響應,更新模型中的資料并向視圖提供所需要的資料。
如果此時沒有弄清楚,并不要緊。在本書結尾處你将完全适應mvc模式,并熟悉如何将其應用到angularjs。從第3章開始我深入到mvc模式的細節,當我在第6章中開始搭建一個更實際的angularjs web應用時,你将開始清晰地看到各個元件之間的區分。
控制器是由調用angular.module所傳回的module對象上的controller方法建立的,如前一節所示。傳給controller方法的參數是新控制器的名稱和一個将會被調用的函數,用于定義控制器功能,如清單2-4所示。
清單2-4 在todo.html檔案中建立一個控制器
慣例一般是對控制器命名為ctrl,這裡的幫助你識别出該控制器在你的應用程式中負責做什麼。真正的應用程式一般會生成多個控制器,但是本例中僅需要一個,名字取為todoctrl。
我承認這個控制器并未能給人留下深刻印象,但這是因為我建立的是一個盡量簡單的控制器。控制器的主要目的之一是為了向視圖提供其所需要的資料。你不會總是希望視圖具有通路整個模型的權限,是以需要使用控制器明确地選出那部分可用的資料,被稱作scope。
傳給我的控制器函數的參數叫作$scope——也就是說,在$符号後緊跟着scope一詞。在一個angularjs應用中,以$開頭的變量名表示angularjs提供的内置特性。當你看到這個$符号時,一般是指一個内置服務,是一種自包含的元件,能夠對多個控制器提供特性,但是$scope是比較特殊的,常用于向視圖暴露資料和功能。我将在第13章中介紹scope,以及在第18~25章中介紹内置服務。
對于這個應用,我想讓視圖中可以使用整個model變量,是以我在$scope服務對象上定義了一個名為todo的屬性,并将整個model變量賦給它,如下:
這麼做是為了能夠在視圖中使用模型資料而做的準備,馬上将會對其進行示範。我還必須指定控制器所負責的html文檔的區域,是通過使用ng-controller屬性來完成的。因為我隻有一個控制器(而且由于這是一個如此簡單的應用),我就對body元素使用了ng-controller屬性,如下:
2.2.4 建立視圖
通過将控制器所提供的資料和用于為浏覽器生成顯示内容的html元素綁定在一起,可以生成視圖。在清單2-5中,你可以看到我是如何使用一種被稱為資料綁定的注釋來對html文檔使用模型資料進行操作的。
清單2-5 在todo.html檔案中通過視圖顯示模型資料
你可以從浏覽器中加載todo.html檔案,進而看到将模型、控制器和視圖綁定在一起所産生的效果,如圖2-3所示。在後面各節中我将解釋html是如何生成的。
1.插入模型值
angularjs使用兩對大括号({{和}})表示一個資料綁定表達式。表達式的内容會被當作javascript計算,僅限于通過控制器賦給作用域上的資料和函數。在本例中,我隻能通路模型中在定義控制器時賦給了$scope對象的那部分,通過使用在$scope對象上建立的屬性名即可。
這就是說,例如,如果我想通路model.user屬性,我得定義一個引用todo.user的資料綁定表達式,這是因為我将model對象賦給了$scope.todo屬性。
angularjs在文檔中對html進行編譯,發現ng-controller屬性後,調用todoctrl函數設定将被用于建立視圖的作用域。當遇到每個資料綁定表達式後,angularjs會查找$scope對象上的具體值,并向html文檔中插入該值。舉個例子,這個表達式:
會被處理并轉換成如下的字元串:
這被稱為資料綁定或者模型綁定,即模型中的值與某個html元素的内容相綁定。有幾種不同的建立資料綁定的方法,将在第10章中加以解釋。
2.計算表達式
資料綁定表達式的内容可以是任何有效的javascript語句,也就是說你可以執行從模型中建立新資料的操作。在清單2-5中,我使用這一特性在清單中顯示待辦事項的個數,如下:
angularjs計算這個表達式并顯示數組中的元素個數,以告訴使用者在待辦事項清單中有多少個元素,在html文檔的header旁邊顯示(使用了bootstrap的label樣式)。
3.使用指令
表達式還經常和指令一起使用,用于告訴angularjs你希望内容如何被處理。在這份清單中用到了ng-repeat屬性,這裡使用了一個指令用于告訴angularjs從一個集合中的各個對象生成所應用到的元素及其内容,如下:
ng-repeat屬性值的格式為 in 。我在todo.items中指定了item,就是說:為todo.items數組中的每個對象生成tr元素和所包含的td元素,并将數組中的對象逐個指派給一個名為item的變量。
使用變量item,我就能夠為數組中的每個對象的屬性定義綁定表達式,産生如下的html。