七步從AngularJS菜鳥(niǎo)到專(zhuān)家(7):Routing
這是"AngularJS – 七步從菜鳥(niǎo)到專(zhuān)家"系列的第七篇。
在第一篇,我們展示了如何開(kāi)始搭建一個(gè)AngularaJS應(yīng)用。在第四、五篇我們討論了Angular內(nèi)建的directives,上一篇了解了services的強(qiáng)大。
在這一章,我們來(lái)看幾個(gè)前面沒(méi)有機(jī)會(huì)細(xì)說(shuō)的關(guān)鍵點(diǎn),文章的最后會(huì)列舉一些特別棒的學(xué)習(xí)資源鏈接和工具。
通過(guò)這整個(gè)系列的教程,我們會(huì)開(kāi)發(fā)一個(gè)NPR(美國(guó)全國(guó)公共廣播電臺(tái))廣播的音頻播放器,它能顯示Morning Edition節(jié)目里現(xiàn)在播出的最新故事,并在我們的瀏覽器里播放。完成版的Demo可以看這里。
7. Routing
在單頁(yè)面應(yīng)用中,視圖之間的跳轉(zhuǎn)就顯尤為重要的,隨著應(yīng)用越來(lái)越復(fù)雜,我們需要用一種方法來(lái)精確控制什么時(shí)候該呈現(xiàn)怎樣的頁(yè)面給用戶(hù)。
咱們可以通過(guò)在主頁(yè)面中引入不同的模板來(lái)支持不同頁(yè)面的切換,但是這么做的缺點(diǎn)就是,越來(lái)越多的內(nèi)嵌代碼導(dǎo)致最后難以管理。
通過(guò)ng-include指令我們可以把很多的模板整合在視圖中,但是我們有更好的方法來(lái)處理這種情況,我們可以把視圖打散成layout和模板視圖,然后根據(jù)用戶(hù)訪問(wèn)的特定的URL來(lái)顯示需要的視圖
我們可以將這些“碎片”在一個(gè)布局模板中拼接起來(lái)
AngularJS通過(guò)在$routeProvider($route服務(wù)的提供者)上聲明routes來(lái)實(shí)現(xiàn)上面的構(gòu)想
使用$routeProvider,我們可以更好的利用瀏覽歷史的API并且可以讓用戶(hù)可以把當(dāng)前路徑存成書(shū)簽以方便以后的使用
在我們的應(yīng)用中設(shè)定路由,我們需要做兩件事情:第一,我們需要指出我們存放將要存放新頁(yè)面內(nèi)容的布局模板在哪里。比如,如果我們想在所有頁(yè)面都配上header和footer,我們可以這樣設(shè)計(jì)布局模板:
- <header>
- <h1>Header</h1>
- </header>
- <div class="content">
- <div ng-view></div>
- </div>
- <footer>
- <h5>Footer</h5>
- </footer>
ng-view指令將高速$routeProvider在哪里渲染模板
第二,我們需要配置我們的路由信息,我們將在應(yīng)用中配置$routeProvider
$routeProvider提供了兩種方法處理路由:when和otherwise。 方法when接收兩個(gè)參數(shù),第一個(gè)設(shè)置$location.path(). (直接用“//”也沒(méi)有問(wèn)題)
第二個(gè)參數(shù)是配置對(duì)象,這個(gè)可以包含不同的鍵,我們可以簡(jiǎn)單的說(shuō)幾個(gè)
controller
- controller: 'MyController'
- // or
- controller: function($scope) {
- // ...
- }
如果在配置對(duì)象中設(shè)置了controller屬性,那這個(gè)controller會(huì)在route加載的時(shí)候?qū)嵗?,這個(gè)屬性可以是一個(gè)字符串(必須在module中注冊(cè)過(guò)的controller)也可以是controller function
Template模板
- template: '<div><h2>Route</h2></div>'
如果我們?cè)谂渲脤?duì)象的template屬性設(shè)置了值,那么模板就會(huì)被渲染到DOM中的ng-view處
templateUrl
- templateUrl: 'views/template_name.html'
如果我們?cè)谂渲脤?duì)象的templateUrl屬性中設(shè)置了值,AngularJS將通過(guò)XHR來(lái)獲取該模板并把模板內(nèi)容渲染到DOM中的ng-view處
值得注意的是:templateUrl屬性跟其他AngularJS XHR請(qǐng)求的處理流程是一樣的,也就是說(shuō),即使用戶(hù)從這個(gè)頁(yè)面離開(kāi),等他再回到這個(gè)頁(yè)面,應(yīng)用不會(huì)再去請(qǐng)求這個(gè)模板頁(yè)面,因?yàn)?templateCache已經(jīng)緩存了這個(gè)模板
添加一些路由
- angular.module('myApp', []).
- config(['$routeProvider', function($routeProvider) {
- $routeProvider.when('/', {
- controller: 'HomeController',
- template: '<h2>We are home</h2>'
- })
- .otherwise({redirectTo: '/'});
- }]);
$routeProvider還可以處理URL里的傳遞的參數(shù)(比如,/people/42, 假設(shè)42是我們要找的people的id號(hào)) 只需要簡(jiǎn)單在字符串前加上 ‘:’,$routeProvider會(huì)嘗試匹配URL中id并把id作為key在$routeParams服務(wù)中使用
- $routeProvider.when('/person/:id', {
- controller: 'PeopleController',
- template: '<div>Person show page: {{ name }}</div>'
- })
在PeopleController中,我們檢索路由中指定的people的:id
- app.controller('PeopleController', function($scope, $routeParams) {
- // We now have access to the $routeParams
- // At the route /person/42, our $routeParams will look like:
- // { id: 42 }
- });
#p#
過(guò)濾器
在AngularJS的世界里,filter提供了一種格式化數(shù)據(jù)的方法,Angular也提供給我們了很多內(nèi)建的過(guò)濾器,并且建立自定義過(guò)濾器也是相當(dāng)?shù)暮?jiǎn)單
在HTML的模板綁定{{}}中,我們使用 | 來(lái)調(diào)用過(guò)濾器,比如,我們想讓字符串全部大寫(xiě)字符顯示
- {{ name | uppercase }}
當(dāng)然了,我們也可以在JavaScript中使用$filter服務(wù)來(lái)調(diào)用過(guò)濾器,還拿字符串大寫(xiě)來(lái)舉例:
- app.controller('DemoController', ['$scope', '$filter',
- function($scope, $filter) {
- $scope.name = $filter('lowercase')('Ari');
- }]);
如何傳遞參數(shù)到filter呢?只需要把參數(shù)放在filter之后,中間加個(gè)冒號(hào)(如果有多個(gè)參數(shù)要傳遞,在每個(gè)參數(shù)后加上冒號(hào))比如,數(shù)字過(guò)濾器可以幫助我們限制數(shù)字的位數(shù),如果想顯示兩位小數(shù),加上number:2就可以了
- {{ 123.456789 | number:2 }}
See it
123.46
我們可以同時(shí)使用N多過(guò)濾器,待會(huì)我們建立自定義的過(guò)濾器的時(shí)候就可以看到如何同時(shí)使用多個(gè)過(guò)濾器,在那之前我們繼續(xù)來(lái)看幾個(gè)Angular自帶的過(guò)濾器
currency
Currency過(guò)濾器主要是把數(shù)字格式化成貨幣,意思就是123格式化以后就成了$123.00
Currency可以根據(jù)需要選擇適當(dāng)?shù)呢泿欧?hào)。默認(rèn)的是根據(jù)當(dāng)前操作系統(tǒng)的locale來(lái)轉(zhuǎn)換的
date
日期過(guò)濾器主要根據(jù)我們提供的格式化形式來(lái)格式化日期,他提供了很多內(nèi)建的選項(xiàng),如果沒(méi)有指定格式,默認(rèn)顯示mediumDate形式
下面是一些自帶的日期格式化形式,我們可以通過(guò)把不同的格式化選項(xiàng)組合使用來(lái)創(chuàng)建自定義的日期格式化形式
#p#
filter
filter過(guò)濾器主要用來(lái)過(guò)濾一個(gè)數(shù)組數(shù)據(jù)并返回一個(gè)包含子數(shù)組數(shù)據(jù)的新數(shù)組
比如,在客戶(hù)端搜索時(shí),我們可以快速的從數(shù)組中過(guò)濾出我們想要的結(jié)果
這個(gè)filter方法接收一個(gè)string,object,或者function參數(shù)用來(lái)選擇/移除數(shù)組元素
If the first parameter passed in is a: | |
String | 接收匹配這個(gè)字符串的元素,如果想排除某些字符串,在前面加上 ‘!’就行了 |
Object | 如果只傳入一個(gè)字符串,會(huì)作為這個(gè)對(duì)象的屬性名稱(chēng)進(jìn)行類(lèi)似substring類(lèi)似的匹配,如果想匹配所有屬性,使用’$’作為鍵即可 |
Function | 對(duì)數(shù)組中每個(gè)元素執(zhí)行這個(gè)function,執(zhí)行后得到的結(jié)果會(huì)放在一個(gè)新的數(shù)組中 |
You can also pass a second parameter into the filter method that will be used to determine if the expected value and the actual 你也可以傳入第二個(gè)參數(shù)到filter方法中,他講用于決定如果期望值和實(shí)際值是否考慮匹配的問(wèn)題
If the second parameter passed in is: | |
true | 執(zhí)行嚴(yán)格的匹配比較(跟’angular.equals(expected,actual)一樣) |
false | 執(zhí)行大小寫(xiě)敏感的substring匹配 |
Function | 執(zhí)行function并接受一個(gè)元素,前提是這個(gè)function的返回結(jié)果是真 |
See it
isCapitalized函數(shù)如下:
- $scope.isCapitalized =
- function(str) { return str[0] == str[0].toUpperCase(); }
json
json 過(guò)濾器接收J(rèn)SON或者JavaScript對(duì)象,然后轉(zhuǎn)換成字符串,這個(gè)功能在調(diào)試程序的時(shí)候非常有用!譯者感受:媽媽再也不用擔(dān)心我的debug,方便的令人發(fā)指
limitTo
limitTo過(guò)濾器會(huì)根據(jù)傳遞的參數(shù)值來(lái)生成新的數(shù)組或字符串,參數(shù)值為整數(shù),從開(kāi)頭截取,參數(shù)為負(fù)值,從最后開(kāi)始截取
如果限定值超過(guò)了字符串長(zhǎng)度,返回整個(gè)數(shù)組或字符串
See it
lowercase
lowercase過(guò)濾器很明顯,將整個(gè)字符串編程小寫(xiě)形式
See it
Lowercase string
- {{ "San Francisco is often cloudy" | lowercase }} san francisco is often cloudy
number
Number過(guò)濾器格式化文本成數(shù)字,可以接受參數(shù)(可選)來(lái)決定格式化后數(shù)字的位數(shù)
如果參數(shù)是非數(shù)字,將返回空字符串
See it
簡(jiǎn)單的數(shù)字格式化
- {{ 1234567890 | number }} 1,234,567,890
格式化數(shù)字到一位小數(shù)
- {{ 1.234567 | number:1 }} 1.2
orderBy
orderBy過(guò)濾器主要是根據(jù)給定的表達(dá)式對(duì)數(shù)組進(jìn)行排序
orderBy函數(shù)可以接受兩個(gè)參數(shù):第一個(gè)是必須要提供的,第二個(gè)是可選參數(shù)
第一個(gè)參數(shù)決定了如何對(duì)數(shù)組進(jìn)行排序
如果傳進(jìn)來(lái)的第一個(gè)參數(shù)是: | |
function | 將被用作這個(gè)對(duì)象的‘getter‘函數(shù) |
string | 字符串會(huì)被作為key來(lái)對(duì)數(shù)組元素進(jìn)行排序,你也可以傳進(jìn)來(lái) ‘+’ 或者‘-‘來(lái)決定是升序還是降序 |
array | 使用這個(gè)數(shù)組里的元素作為排序表達(dá)式的判斷依據(jù),使用第一個(gè)不嚴(yán)格相等表達(dá)式的結(jié)果的元素作為其他元素的判斷依據(jù) |
The second parameter controls the sort order of the array (either reversed or not).
See it
根據(jù)人名排序
uppercase
Uppercase過(guò)濾器就是把整個(gè)字符串變成大寫(xiě)形式
See it
- {{ "San Francisco is often cloudy" | uppercase }} SAN FRANCISCO IS OFTEN CLOUDY
#p#
創(chuàng)建自定義的過(guò)濾器
正如我們前面看到的,創(chuàng)建自定義過(guò)濾器相當(dāng)簡(jiǎn)單,我們只要把他配置到我們的module下就可以了,讓我們一起來(lái)創(chuàng)建一個(gè)首字母大寫(xiě)的過(guò)濾器吧
首先,我們創(chuàng)建一個(gè)module
- angular.module('myApp.filters', [])
- .filter('capitalize', function() {
- return function(input) {}
- });
Fliters其實(shí)就是一個(gè)function,接收input 字符串,我們可以函數(shù)里做一些錯(cuò)誤檢查
- angular.module('myApp.filters', [])
- .filter('capitalize', function() {
- return function(input) {
- // input will be ginger in the usage below
- if (input)
- return input[0].toUpperCase() + input.slice(1);
- }
- });
See it
還有一些話(huà)題是我們還沒(méi)來(lái)得及討論
在這個(gè)系列教程中,我們介紹了很多可以讓你輕松上手AngularJS的知識(shí)點(diǎn),當(dāng)然了,還有很多要點(diǎn)沒(méi)有機(jī)會(huì)談到,都列在下面,希望以后有機(jī)會(huì)跟他家一起研究
- Promises (可以讓多個(gè)異步請(qǐng)求更加的有條理)
- Building custom directives(自定義指令)
- $resource service($resource 服務(wù),非常好用的一個(gè)服務(wù),底層是調(diào)用了$http Service)
- Unit testing(單元測(cè)試,這個(gè)尤為重要,甚至可以單拿出來(lái)講很多,推薦jasmine)
- End-to-end testing(同上)
- Midway testing(介于前面兩者的測(cè)試)
- i18n and I10n language translation/localization(多語(yǔ)言)
- Authentication and customizing XHR requests(驗(yàn)證和自定義XHR請(qǐng)求)
- Using the $provide service to build customizable services(使用$provider服務(wù)來(lái)創(chuàng)建自定義服務(wù))
- Forms and validations(表單和驗(yàn)證)
- IE compatibility(IE兼容性)
原文鏈接:http://blog.jobbole.com/50533/