代碼稍多,請自行打開
一、前言早已聽說AngularJS的大名,並在很久前也編寫過些小demo,但是都沒有系統學習過。由於,在下個版本項目中用到了AngularJS,so,那就一起再來研究研究呗。
說到,這個AngularJS,其核心就是對HTML標簽的增強。
何為HTML標簽增強?
其實就是使你能夠用標簽完成一部分頁面邏輯,具體方式就是通過自定義標簽、自定義屬性等,這些HTML原生沒有的標簽/屬性在ng中有一個名字:指令(directive)。
至於說AngularJS是MVC,亦或MVVM框架?
都不是,它是MVW,最後的W意思就是說whatever,固有些人也稱其為MV*。其中含義,以後實踐久了,應該就豁然開朗了,至於現在,move on吧。
二、一切從hello world開始啊,蒼茫的天涯是我的愛,綿綿的青山腳下花會開,什麼樣的節奏是最呀最搖擺,什麼樣的歌聲才是最開懷~~~
現在這個年代,人非草木,什麼都得有情懷,不然還混不下去了。所以,接下來我們編寫個小demo,來抒發我們的抱負。
這個demo要實現的功能很簡單,就是在input框中,輸入自定義內容,如hello world,間接改變另一顯示區域。
前提:如若沒有angular.js文件,請點擊這裡(here)。
實現代碼如下:
<!DOCTYPE html>效果圖:
怎麼樣,是八是很驚奇,僅僅用了這幾行代碼,就實現了這個效果,倘若利用原生代碼實現,我們還得監聽input框,值若改變,取值,將其動態插入h1中。
啧啧啧,相對於AngularJS顯得稍稍笨重了許多,所以這也體現了AngularJS的優點,適合數據操作多的應用。
在“前言”中,我們已經提到,AngularJS其核心就是對HTML標簽的增強,且內置的Angular指令是以ng-開頭的,如上述代碼中的ng-app以及ng-model。
--ng-app指令聲明所有被其包含的內容都屬於angularjs應用
--ng-model指令將內部$scope的屬性名綁定到input框中,從而實現雙向綁定。
好了,倘若我想給上述input框一個默認值 ’hello world’ 呢?在value=’hello world’?
噗,No。因為我們在body已用ng-app指令表示在body中都屬於angular應用啦,so
<input type='text' ng-model='custom' value='hello world'/>
是不起作用滴,不過可以利用angular內置指令ng-init來達到我們想要的效果。
代碼如下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app> <input type="text" ng-model="custom" ng-init="custom='hello world'"/> <h1>{{custom}}</h1> </body> </html>
除開這種便捷的方法,我們還可以利用控制器來實現同樣的效果。
如下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app> <input type="text" ng-model="custom" ng-controller="customController"/> <h1>{{custom}}</h1> <script> function customController($scope){ $scope.custom = 'hello world'; } </script> </body> </html>
效果圖如下:
尼瑪,怎麼不是我們想要的效果?!!
細看代碼,發現,我們將控制器customController寫在input中的,固出現上述狀況。
你可能會問,這是為什麼呢?-.-小沈陽附體
因為諸如ng-app、ng-controller這些標簽,他們都會創建一個作用域,這個作用域呢,又是以html標簽來劃分的。如<body ng-app>,那麼它所創建的作用域($rootScope),就是在body中生效,即</body>止。如上述代碼,我們將控制器customController寫在input中,那麼這個子作用域就是在input中,<h1>標簽中的{{custom}}是獲取不到的。
好了,了解了原因,我們修改上述代碼,如下,將customController控制器放到body中,即可。
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app ng-controller="customController"> <input type="text" ng-model="custom"/> <h1>{{custom}}</h1> <script> function customController($scope){ $scope.custom = 'hello world'; } </script> </body> </html>
完美!
咦,函數customController中參數$scope什麼鬼,我們調用時並沒有傳入呢。這就涉及到Angular的另一核心特效依賴注入,我們現在先不管他內部原理如何實現的,大概過程就是將預定義好的對象名與具體操作綁定,我們使用時,在參數中調用即可,且注入名字必須與預定義的對象一樣,不然會報錯。另,$scope對象屬於Angular內置對象,代表對應的作用域管理對象。
上述代碼中,再細細看來,還是不好呢。我們將控制器寫在了全局對象中,雖然不影響代碼運行,但不易於維護嘛,好在Angular允許我們使用angular.module方法來聲明模塊。
該方法接收兩個參數,第一個是模塊的名稱,第二個是依賴列表。利用angular.module修改上述代碼,得下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app='myApp' ng-controller="customController"> <input type="text" ng-model="custom"/> <h1>{{custom}}</h1> <script> var myApp = angular.module('myApp', []); myApp.controller('customController', function($scope){ $scope.custom = 'hello world'; }); </script> </body> </html>
效果圖如下:
三、scope作用域AngularJS 應用啟動並生成視圖時,會將根 ng-app 元素與 $rootScope 進行綁定,$rootScope 是所有 $scope 的最上層對象,可以理解為一個 AngularJS 應用中的全局作用域對象,所以為它附加太多邏輯或者變量並不是一個好主意,和污染 Javascript 全局作用域是一樣的。通過諸如控制器、指令等這些命令,我們可以創建子作用域,所有的子作用域都通過原型繼承而來(指令的孤立作用域除外),也就是說它們都可以訪問父級作用域。
好了,我們通過編寫個demo感受一番:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app='myApp'> rootScope:{{name}} <div ng-controller="outterController"> outter:{{name}} <div ng-controller="innerController"> inner:{{name}} </div> </div> <script> var myApp = angular.module('myApp', []); myApp.run(function($rootScope){ $rootScope.name = 'rootScope'; }).controller('outterController', function($scope, $timeout){ $timeout(function(){ $scope.name = 'outter'; }, 1000); }).controller('innerController', function($scope, $timeout){ $timeout(function(){ $scope.name = 'inner'; }, 2000); }); </script> </body> </html>代碼稍多,請自行打開
效果圖如下:
四、過濾器
Angular過濾器用來格式化需要展示給用戶的數據,通過 | 符號來達到過濾效果。
假設我們需要在將一個數字過濾,讓他保留兩位小數,可以這麼做:
{{124.567 | number:2}}//124.57 {{124 | number:2}}//124.00
並且,我們可以使用多個filter連用,上一個filter的輸出結果將作為下一個filter的輸入,如:
{{ expression | filter1 | filter2| … }}
上述代碼中的number為Angular的內置過濾器。如果我們需要傳遞參數給過濾器,只要在過濾器名字後面加冒號即可。如果有多個參數,可以在每個參數後面都加入冒號。
Angular內置的過濾器有:currency(貨幣)、date(日期)、filter(子串匹配)、json(格式化json對象)、limitTo(限制個數)、lowercase(小寫)、uppercase(大寫)、number(數字)、orderBy(排序),總共九種,除此之外還可以自定義過濾器,這樣,我們就可以滿足任何要求的數據處理啦。
下面先列舉幾個常用的內置過濾器,拋磚引玉,大家一同感受下。
1、 filter
filter過濾器可以從給定數組中選擇一個子集,並將其生成一個新數組返回。這個過濾器通常用來過濾需要進行展示的元素。該過濾器有兩個參數,第一個參數可以是字符串、對象或是一個用來從數組中選擇元素的函數。下面一一介紹:
--字符串--
返回所有包含這個字符串的元素。如果我們想返回不包含該字符串的元素,在參數前面加 !符號即可。
如下:
{{['Ari', 'Lerner', 'Likes', 'To', 'Eat', 'Pizza'] | filter:'!e'}}
--對象--
AngularJS會將待過濾對象的屬性同這個對象中的屬性名進行一一比較,如果過濾對象的屬性包含這個屬性名,則出現在新的數組中並返回。
如下:
{{[{'name': 'Ari', 'age': 3 },
{ 'name': 'Nate', 'age': 33 }] | filter: {'age': 3} }}
--函數--
對每個元素都執行這個函數,返回非假值得元素會出現在新的數組中並返回。
如下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app='myApp'> {{ ['Ari', 'likes', 'to', 'travel'] | filter: isCapitalized}} <script> var app = angular.module('myApp', []); app.run(function($rootScope){ //isCapitalized有且僅有一個參數 $rootScope.isCapitalized = function(str){ return str[0] === str[0].toUpperCase(); }; }); </script> </body> </html>
Angular過濾器的第二個參數,可以是true。
--true--
對比較值進行,嚴格比較,如下:
{{ ['Ari', 'likes', 'to', 'travel', 'e'] | filter: 'e' : true}}
2、 number
number過濾器將數字格式化成文本,可以為一個數字加上千位分割符,如12345變為12,345。它的參數是可選的,用來控制小數點後的截取位數。另外,傳入的是一個非數字字符,會返回空字符串。
如下:
{{12345 | number:2}}
3、 orderBy
orderBy過濾器可以將一個數組中的元素進行排序,接收一個參數來指定排序規則,參數可以是一個字符串,表示以該屬性名稱進行排序。可以是一個函數,定義排序屬性。還可以是一個數組,表示依次按數組中的屬性值進行排序(若按第一項比較的值相等,再按第二項比較),如下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app='myApp'> <div>{{ childrenArray | orderBy : 'age' }}</div><!--按age屬性值進行排序,若是-age,則倒序--> <div>{{ childrenArray | orderBy : ['age','name'] }}</div><!--如果age相同,按照name進行排序--> <div>{{ childrenArray | orderBy : orderFunc }}</div><!--按照函數的返回值進行排序--> <script> var app = angular.module('myApp', []); app.run(function($rootScope){ $rootScope.childrenArray = [ {name:'Tom', age: 20}, {name:'Mari', age:19}, {name:'Ari', age: 21}, {name:'Jack', age: 19} ]; $rootScope.orderFunc = function(ele){ return [ele.age, ele.name]; } }); </script> </body> </html>代碼稍多,請自行打開
通過上面的例子,我們對Angular內置的過濾器有了一定了解。那麼,接下來,我們就一起來看看自定義過濾是如何實現的。
Angular的自定義過濾器也比較簡單,使用module的filter方法,返回一個函數搞定,且該函數接收的參數值就是過濾值,最後返回處理後的結果。
如下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <script src="angular.js"></script> </head> <body ng-app='myApp'> {{ [1,2,3,4,5,6] | filterNumber}} <script> var app = angular.module('myApp', []); app.filter('filterNumber', function(){ return function(input){ var arr = [], len, val; if(input){ len = input.length; while(len--){ (val = input[len]) > 3 && arr.push(val); } } return arr; } }); </script> </body> </html>
好了,就先暫且探到這兒吧。
一些AngularJS相關文章鏈接:
AngularJS權威教程 清晰PDF版 http://www.linuxidc.com/Linux/2015-01/111429.htm
希望你喜歡,並分享我的工作~帶你走近AngularJS系列:
如何在 AngularJS 中對控制器進行單元測試 http://www.linuxidc.com/Linux/2013-12/94166.htm
在 AngularJS 應用中通過 JSON 文件來設置狀態 http://www.linuxidc.com/Linux/2014-07/104083.htm
AngularJS 之 Factory vs Service vs Provider http://www.linuxidc.com/Linux/2014-05/101475.htm
AngularJS —— 使用 ngResource、RESTful APIs 和 Spring MVC 框架提交數據 http://www.linuxidc.com/Linux/2014-07/104402.htm
AngularJS 的詳細介紹:請點這裡
AngularJS 的下載地址:請點這裡