本章我們將把手機(jī)的詳情頁(yè)做詳細(xì)一點(diǎn)鲫竞。改動(dòng)很簡(jiǎn)單:
- 當(dāng)點(diǎn)擊列表頁(yè)中的某個(gè)手機(jī)時(shí)辐怕,手機(jī)詳情頁(yè)將被展示。
另外比較有趣的是从绘,這次詳情頁(yè)的數(shù)據(jù)獲取我們將借助$http
服務(wù)來(lái)完成寄疏。
使用git遷出step-8分支就是該章對(duì)應(yīng)的實(shí)例代碼:
git checkout -f step-8
刷新你的瀏覽器來(lái)看效果是牢,或者可以點(diǎn)這里在線查看。
數(shù)據(jù)
除了phones.json
之外陕截,app/phones/
目錄下還為每個(gè)手機(jī)創(chuàng)建了詳情數(shù)據(jù)驳棱,分別對(duì)應(yīng)一個(gè)json文件:
app/phones/nexus-s.json
(樣例片段)
{
"additionalFeatures": "Contour Display, Near Field Communications (NFC),...",
"android": {
"os": "Android 2.3",
"ui": "Android"
},
...
"images": [
"img/phones/nexus-s.0.jpg",
"img/phones/nexus-s.1.jpg",
"img/phones/nexus-s.2.jpg",
"img/phones/nexus-s.3.jpg"
],
"storage": {
"flash": "16384MB",
"ram": "512MB"
}
}
每個(gè)文件的結(jié)構(gòu)是一樣的,只是具體參數(shù)的值不一樣艘策。詳情頁(yè)視圖將會(huì)展示這些數(shù)據(jù)。
控制器
我們將對(duì)PhoneDetailCtrl
控制器做一點(diǎn)擴(kuò)展:使用$http
服務(wù)來(lái)獲取JSON格式文件渊季。
這和列表頁(yè)獲取手機(jī)列表控制器是類似的朋蔫。
app/js/controllers.js
var phonecatControllers = angular.module('phonecatControllers',[]);
phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
function($scope, $routeParams, $http) {
$http.get('phones/' + $routeParams.phoneId + '.json').success(function(data) {
$scope.phone = data;
});
}]);
我們使用由$route
服務(wù)從當(dāng)前路由地址中抽取的¥routeParams.phoneId
變量來(lái)構(gòu)建不同手機(jī)的不通HTTP請(qǐng)求的URL地址。
模版
我們把之前的TBD占位行替換成了手機(jī)詳情內(nèi)容却汉。注意我們是在哪里使用{{expression}}
標(biāo)記和ngRepeat
指令來(lái)完成模型到視圖的數(shù)據(jù)傳遞的驯妄。
app/partials/phone-detail.html
<img ng-src="{{phone.images[0]}}" class="phone">
<h1>{{phone.name}}</h1>
<p>{{phone.description}}</p>
<ul class="phone-thumbs">
<li ng-repeat="img in phone.images">
<img ng-src="{{img}}">
</li>
</ul>
<ul class="specs">
<li>
<span>Availability and Networks</span>
<dl>
<dt>Availability</dt>
<dd ng-repeat="availability in phone.availability">{{availability}}</dd>
</dl>
</li>
...
<li>
<span>Additional Features</span>
<dd>{{phone.additionalFeatures}}</dd>
</li>
</ul>
測(cè)試
我們寫了一個(gè)和第七章中為PhoneListCtrl
控制器寫的差不多的單元測(cè)試:
test/unit/controllersSpec.js
beforeEach(module('phonecatApp'));
...
describe('PhoneDetailCtrl', function(){
var scope, $httpBackend, ctrl;
beforeEach(inject(function(_$httpBackend_, $rootScope, $routeParams, $controller) {
$httpBackend = _$httpBackend_;
$httpBackend.expectGET('phones/xyz.json').respond({name:'phone xyz'});
$routeParams.phoneId = 'xyz';
scope = $rootScope.$new();
ctrl = $controller('PhoneDetailCtrl', {$scope: scope});
}));
it('should fetch phone detail', function() {
expect(scope.phone).toBeUndefined();
$httpBackend.flush();
expect(scope.phone).toEqual({name:'phone xyz'});
});
});
...
你將看到Karma的輸出:
Chrome 22.0: Executed 3 of 3 SUCCESS (0.039 secs / 0.012 secs)
我們還寫了一個(gè)端到端測(cè)試來(lái)測(cè)試詳情頁(yè)的Heading是不是“Nexus S”。
test/e2e/scenarios.js
...
describe('Phone detail view', function() {
beforeEach(function() {
browser.get('app/index.html#/phones/nexus-s');
});
it('should display nexus-s page', function() {
expect(element(by.binding('phone.name')).getText()).toBe('Nexus S');
});
});
...
然后可以重新運(yùn)行npm run protractor
來(lái)查看測(cè)試運(yùn)行
實(shí)驗(yàn)小能手
使用Protractor API
合砂,寫一個(gè)測(cè)試用例青扔,用來(lái)驗(yàn)證Nexus詳情頁(yè)4張照片是否顯示正確。(注解:覺(jué)得復(fù)雜就別做了翩伪。沒(méi)啥微猖。)
總結(jié)
下一章我們將學(xué)習(xí)如何編寫自己的過(guò)濾器。