Angular js是一個Web應用框架,它極其流行,已經成爲目前使用最普遍的Javascript工具之一。Ionic基於AngularJS構建而成,因此學習一些AngularJS的知識頗有必要。Ionic並無獨立開發一套完整的Web應用框架,而是對AngularJS進行了擴展,給它添加了大量界面組件和其餘的移動端友好的特性。javascript
本篇文章會帶你瞭解AngularJS的核心知識並介紹一些基礎知識。咱們學會控制器,顧名思義,它會控制(control)你的數據。接着咱們介紹做用於,它會鏈接控制器和用戶界面,後者被稱爲視圖(view)。仔細觀察視圖,你會看到他們是如何經過模板和做用域來建立交互視覺效果的。在這個過程當中,咱們還會學習其它特性,好比如何使用過濾器來轉換數據、如何構建並使用指令來加強現有的HTML元素,以及如何從外部數據源中加載並保存應用數據。java
如今咱們來看一個bootstrap+AngularJS開發的一個小應用,方便咱們瞭解AngularJS。你能夠草叢GitHub上查看完整的項目代碼https://github.com/ionic-in-action/chapter3。若是你想看最終的效果,能夠訪問https://ionic-in-action/chapter3.herokuapp.comgit
AngularJS和HTML關係密切,尤爲是在你建立模板的時候。模板是一塊HTML內容,能夠再須要的時候載入應用。AngularJS向HTML中加入了許多新特性並擴充了HTML的語義。視圖會使用模板來展現數據。視圖必定會有一個模板(就是HTML標籤),還會有模板須要用到數據。視圖會把模板轉換成用戶最終看到的視覺效果,也就是說,它會基於數據修改模板。下面咱們來看一段模板github
<ul class="list-group"> <li class="list-group-item" ng-repeat="note in notes" ng-click="displayNote($index)" ng-class="{active:note.id==content.id}"> {{note.title}}<br/> <small>{{note.date|date:'short'}}</small> </li> </ul>
這段模板展現的只是<ul>中的一個<li>元素,它包含多個被稱爲Angular指令的屬性。指令會修改包含它的元素行爲。在本例中,ng-Repeat會遍歷一個Javascript對象或者數組,併爲每一個元素建立一個<li>元素。ng-click相似Javascript的onClick時間處理器,單擊時會調用displayNote()函數。這個模板被渲染時會爲notes數組中的每一個元素建立一個列表元素。bootstrap
雙花括號({{}})表示某些數據會被展現在這裏,這種思想被稱爲數據綁定,這種語法叫作表達式花括號中的全部內容都是表達式,Angular會用當前模型的數據對錶達式求值。所以,note.title的內容會被插入到<li>元素中花括號包裹的位置。模板就是帶有指令或表達式的HTML。視圖會獲取數據並使用數據中的值來對模板進行渲染。假設notes數組中有5個筆記,<ul>元素會包含5個列表元素,如圖。數組
Angular有不少自帶的指令,它們都以ng開頭。有些用來修改顯示樣式(如ng-show、ng-class),有些用於表單(如ng-model、ng-Form),有些用於監聽點擊等各類事件(如ng-click、ng-mouseover)。Angular還有許多做用在原生HTML元素上的指令,提供一些HTML沒有的功能,這些元素包括輸入框、文本區域和錨點。舉個例子,Angular能夠給<input type="text">元素添加額外的屬性,讓它支持自定義驗證。完整的列表請查閱Angular官方文檔。app
控制器是附加在文檔對象模型(DOM)節點上的函數,用來驅動你的應用邏輯。在Javascript中,控制器就是一個函數,用來和做用域通訊並響應時間。框架
做用域能夠理解爲在控制器和視圖之間共享的一個上下文。能夠把它看作控制器和界面的橋樑,做用域在控制器中更新時也會更新視圖。做用域有兩個核心角色:存儲數據並容許控制器的方法訪問數據。存儲在做用域中的數據被稱爲模型。模型能夠是任意Javascript值(同城是數組或者對象,也能夠是簡單的數據或者字符串),你能夠把它存儲在做用域中,而後經過做用域共享個控制器和視圖。咱們來看一個例子,它會把上圖的視圖和模板結合起來:ionic
angular.module("App") .controller('Controller',function($scope){ $scope.notes=[ {id:1,title:'Note 1',date:new Date()} , {id:2,title:'Note 2',date:new Date()} ]; $scope.getNote=function(index){ $scope.content=$scope.notes[$index]; } });
這個控制器會使用一個數組中的元素來設置notes模型,後者存儲在一個特殊的$scope對象中。這個對象是Angular提供的,每一個做用域都有,你能夠存儲數據並在控制器和視圖(也就是模型)中共享數據。視圖會使用ng-repeat在列表中展現筆記數組。getNote()方法能夠幫你聲明哪些筆記須要存儲在content模型中。視圖能夠調用這個方法,由於它們在同一個做用域中。函數
控制器中的全部內容都和應用的其餘部分隔離,除了它本身的子做用域。這很重要,由於這能夠限制代碼和變量的可見性。對於一個新Angular開發這來講,常見的挑戰就是訪問不一樣做用域中的內容,默認狀況下是不可能實現的。
Angular的做用域是有層級結構的,做用域能夠想DOM同樣嵌套。實際上,做用域對應頁面上的DOM結構。做用域能夠經過附加實現只容許一個HTML元素及其它子元素訪問,就像CSS類能夠將目標樣式應用在設置類的元素及子元素同樣。
當想進行跨做用域通訊時,層級結構變得尤爲重要,由於子做用域能夠查看父做用域(就像Javascript的原型繼承同樣,若是你很熟悉的話)。Angular中的一些指令會建立子做用域,所以有時候不太好判斷具體的做用域。若是你在子做用域中訪問一個不存在的值,它實際上會在父做用域中尋找那個值,直到找到或者遍歷完全部的父做用域。
根做用域(經過特殊的$root Scope對象訪問)是Angular建立的第一個做用域,是其它全部做用域的基礎。這意味着你放在根做用域上的全部東西對其它做用域都是可見的,聽起來彷佛還不錯,但最好不要這樣作。須要保持做用域整潔和聚焦,而不是把全部東西都堆在根做用域裏。Javascript的做用域就有這個問題,應用一般使用全局做用域來保存變量。假設你有一個名爲id的值;若是你的子做用域也有一個id,就會出現衝突,你沒法訪問根做用域中的值。協同開發時這個問題會更加突出,由於開發同一個應用的人越多或者你使用的外部工具越多,那就越有可能出現命名衝突。
注意:控制器不是萬能的
有一些事實不該該在控制器中作的,由於它們會讓你的代碼更難維護和測試。最重要的是避免在控制器中進行DOM操做,假設你在構建一個幻燈片效果,控制器不該該改動DOM或者改變幻燈片的樣式,由於這應該有自定義指令實現。你還應該避免在控制器中格式化或者過濾數據,可以使用表單來作這些是。
Angular中有一個概念交service,它本質上就是一個javascript對象,能夠在整個應用中共享。Angular默認提供了許多service,你能夠建立本身的service。若是你已經嘗試過Angular,那你確定用過自帶的service。
$http是一個很是常見的service,Angular用它來操做HTTP請求。它有不少方法,好比get()、post()和其餘的HTTP動做。service能夠很是複雜(好比$http),也能夠簡單的只包含一些數據。
service是有Angular延遲加載的,也就是說,它們只會在使用的時候才載入內存。它們仍是單例的,若是你在一個地方改變了service的值,其它用到這個service的地方都會受影響。Ionic把許多特性寫成了Angular的service,須要記住的是,控制器中包含的幾乎全部的內容都是service。
Angular最強大的特性之一就是雙向數據綁定。你已經看到了視圖如何把數據綁定到模板,其實反過來一樣適用。視圖能夠改變做用域中的數據,數據會馬上更新到做用域並反應到控制器中。這在表單中尤爲有用,用戶向文本框中輸入內容時,做用域中的值會同步更新。你不須要作任何特殊的事情來啓動雙向數據綁定——她會自動實現。