簡介:在本節課中,咱們將會經過一個虛構的旅遊景點來構建一款功能完善的應用。本應用的核心特性是管理用戶的應用內導航。本節課的主要目的,是展示構建一個完整的應用的過程。css
不管是什麼移動應用,最重要的功能之一都是讓用戶能夠在應用內導航,首先須要設置應用導航必要的基礎部分,而後繼續使用Ionic用戶界面組件來構建新界面,全部組件協同工做,讓應用能夠顯示天氣信息,遊客的預訂信息以及附近的景點信息,應用還會使用一個簡單的幻燈片來作新手指引,這個在許多應用中咱們都有見到。html
下面咱們先來展現一下基本的 應用流程圖:ios
下面進入開發環節:api
4.1 配置項目數組
咱們先來配置項目,基礎環境,我在第二節課的時候已經講過了,如今先來看看版本:服務器
咱們先來建立一個空的項目,執行命令:併發
安裝完成後進入文件夾:app
啓動服務:框架
咱們會看到這樣一個頁面:ionic
4.2 配置應用導航
開始構建應用以前,咱們來看下用戶能夠訪問的視圖都有哪些~
以上圖片展現的只是概覽,咱們須要構建每一個視圖,下面咱們先來配置應用導航,而後再給每一個視圖添加內容。Ionic支持第三方路由框架ui-router,它是導航的中央大腦,Ionic就是在ui-router基礎上開發的,因此不須要關心底層細節,除非要開發自定義的導航功能。
如今,咱們來理解一下導航和路由的概念。導航是指用戶在應用內部移動的動做,路由是指應用內部的過程,用於控制用戶導航時具體的行爲。換句話來解釋,就是導航時用戶的行爲,路由是應用響應用戶輸入的邏輯。
咱們的第一個任務是嚮應用的index.html文件添加一個Ionic導航組件,而後再聲明一個起始視圖。
ionNavView和ionNavBar是Ionic的基礎組件,用於導航。ionNavView就像一個佔位符,用於把不一樣的視圖內容載入應用,ionNavBar是標題欄,在用戶跳轉新視圖時自動更新。這兩個組件是一同工做的,不過若是你不想要頂部的導航欄,也能夠單獨使用ionNavView。ionNavBar在應用的頂部,咱們能夠在這裏放置當前視圖的標題,也能夠放置按鈕,若是返回按鈕,在咱們的應用中,會使用ionNavBackButton組件來實現一種返回方式。
打開index.html文件,加入導航組件:
<!-- 把angular應用插入頁面 --> <body ng-app="starter"> <!-- 聲明ionNavBar,而且添加bar-positive類 --> <ion-nav-bar class="bar-positive"> <!-- 聲明ionNavBackButton,若是有上一級視圖就會出現 --> <ion-nav-back-button class="button-clear"> <!-- 用返回箭頭圖標來當作返回按鈕 --> <i class="icon ion-ios-arrow-left"></i> Back </ion-nav-back-button> <!-- 聲明ionNavView,這裏會顯示每一個視圖的內容 --> </ion-nav-bar> <ion-nav-view></ion-nav-view> </body>
咱們如今運行代碼,會發現頁面上什麼功能都沒有,這是由於咱們尚未聲明任何視圖。而後咱們須要來聲明應用的一些列狀態,狀態是ui-router的一個概念,狀態對應應用當前須要顯示的視圖,其中會包括視圖對應的URL、視圖控制器的名字和視圖對應的模板。
下面咱們來聲明第一個狀態-->home狀態,打開www/js/app.js文件:
angular.module('starter', ['ionic']) //添加新的config方法並注入$stateProvider .config(function($stateProvider,$urlRouterProvider){ //聲明第一個狀態對應的是主視圖 $stateProvider.state('home', { //給狀態設置一個URL,能夠用在錨點鏈接上 url:'/home', //視圖激活時,讓這個狀態從指定的URL加載模板 templateUrl:'view/home/home.html' }); //聲明降級URL,若是應用找不到請求的狀態會跳轉到這裏 $urlRouterProvider.otherwise('/home'); }) .run(function($ionicPlatform) {...
上面的代碼中,咱們使用$stateProvider服務來聲明狀態,用$urlRouterProvider在請求無效的時候指定跳轉地址。otherwise()方法很是重要,由於它會在應用沒法找到目標路由時發揮做用,好比王章的404錯誤。若是用戶試圖請求一個不存在的狀態,otherwise()方法會顯示主視圖,因此最好保證有otherwise()方法。
咱們在上面聲明瞭一個模板,可是沒有建立對應的文件,下面咱們就來建立主視圖文件。建立新文件www/views/home/home.html文件並寫入以下代碼:
<ion-view view-title="旅遊啦" hide-back-button="true"> </ion-view>
如今運行代碼,咱們能夠看到這樣的頁面:
注意hide-back-button屬性,它控制視圖是否可見返回按鈕。
4.3 構建主視圖
如今項目只有一個帶標題的空視圖,咱們須要給視圖添加內容。這時,咱們須要用到ionContent來建立內容容器,這是一個通用的內容封裝器,它有不少特性:根據設備調整內容區域的尺寸、和頭部底部協同合做、管理滾動。最經常使用的就是管理滾動。下面咱們打開home.html文件,加入以下內容:
<ion-view view-title="旅遊啦" hide-back-button="true"> <!-- 顯示主視圖的內容 --> <ion-content> </ion-content> </ion-view>
如今有了內容容器了,咱們須要嚮應用中添加一個基礎的列表組件,仍是打開home.html文件,加入以下內容:
<ion-view view-title="旅遊啦" hide-back-button="true"> <!-- 顯示主視圖的內容 --> <ion-content> <!-- 給容器元素添加list類,從而指定它爲列表容器 --> <div class="list"> <!-- 給元素添加item類,從而建立一個列表元素,這裏它會連接到其餘視圖 --> <a href="#/reservation" class="item">預訂信息</a> <a href="#/weather" class="item">本地天氣</a> <a href="#/restaurants" class="item">附近餐館</a> </div> </ion-content> </ion-view>
如今頁面效果以下圖所示:
如今,咱們來給主視圖的列表項添加圖標,ionic自帶許多的圖標,它們被稱爲ionicons。
打開home.html文件,咱們來給主視圖添加圖標:
<ion-view view-title="旅遊啦" hide-back-button="true"> <!-- 顯示主視圖的內容 --> <ion-content> <!-- 給容器元素添加list類,從而指定它爲列表容器 --> <div class="list"> <!-- 給元素添加item類,從而建立一個列表元素,這裏它會連接到其餘視圖,添加item-icon-left類來獲取咱們想要的效果 --> <a href="#/reservation" class="item item-icon-left"> <!-- 給i元素添加圖標類,就能夠展現圖標了 --> <i class="icon ion-document-text"></i> 預訂信息 </a> <a href="#/weather" class="item item-icon-left"> <i class="icon ion-ios-partlysunny"></i> 本地天氣 </a> <a href="#/places" class="item item-icon-left"> <i class="icon ion-fork"></i> 附近景點 </a> </div> </ion-content> </ion-view>
主視圖效果以下圖所示:
4.4 使用控制器和模型來開發預訂視圖
對於預訂視圖,因爲咱們須要加載用戶的數據並顯示出來,因此可使用控制器來管理數據。下面咱們先來建立一個新的控制器,建立文件www/views/reservation/reservation.js:
//引入angular模塊 angular.module('starter') //聲明控制器的名字和函數,接受一個元素到列表並注入$scope中 .controller('ReservationController', function($scope){ //把模型對象賦值給$scope $scope.reservation = { //設定停留日期 checkin:new Date(), checkout:new Date(Date.now()+1000*60*60*24*7), //設置預訂須要的其餘靜態值 room:208, rate:121, wifi:'208wifi', wificode:'888888' }; });
下面咱們來構建一下預訂視圖,建立www/views/reservation/reservation.html文件:
<ion-view view-title="預訂信息"> <ion-content> <!-- 使用列表組件包裹列表 --> <div class="list"> <div class="item item-icon-left"> <!-- 設置圖標,把數據綁定到模板中 --> <i class="icon ion-key"></i> 房間號:{{reservation.room}} </div> <div class="item item-icon-left"> <i class="icon ion-calendar"></i> 入住時間:{{reservation.checkin | date:'mediumDate'}} </div> <div class="item item-icon-left"> <i class="icon ion-calendar"></i> 離開時間:{{reservation.checkout | date:'mediumDate'}} </div> <div class="item item-icon-left"> <i class="icon ion-wifi"></i> WIFI:{{reservation.wifi}} </div> <div class="item item-icon-left"> <i class="icon ion-wifi"></i> WIFICode:{{reservation.wificode}} </div> <div class="item item-icon-left"> <i class="icon ion-pricetag"></i> 單價:{{reservation.rate | currency}}/晚 </div> <div class="item item-icon-left"> <i class="icon ion-pricetags"></i> 總價:{{reservation.rate * 7 | currency}} </div> </div> </ion-content> </ion-view>
如今,咱們有了預訂視圖以及將數據顯示出來,剩下的只須要把這個視圖添加到應用的狀態管理器當中,打開app.js文件,接着主視圖添加如下代碼:
//聲明預覽視圖的狀態 .state('reservation', { //使用/reservation URL來標識這個狀態 url: '/reservation', //聲明這個視圖用到的控制器的名稱 controller: 'ReservationController', //聲明要加載的視圖文件 templateUrl: 'views/reservation/reservation.html' });
而後,把reservation.js文件引入到index.html文件的</head>標籤前面。此時,咱們的預訂視圖已經完成了,預覽效果以下圖:
4.5 把數據加載到天氣視圖中
如今咱們來完整天氣視圖,天氣視圖的功能是從外部服務器載入天氣數據,因此咱們先來配置控制器來加載外部天氣數據。咱們須要使用到Angular提供的$http服務來從一個URL加載數據,把$http服務注入到控制器,訪問一個URL,而後處理HTTP請求的成功或者失敗的狀況。首先咱們先來建立一個新的控制器文件www/views/weather/weather.js:
//引用angular模塊 angular.module('starter') //聲明控制器並注入$scope和$http服務 .controller('WeatherController', function($scope, $http){ //聲明包含全部可能風向的數組 var directions = ['北','東北','東','東南','南','西南','西','西北']; //發起HTTP請求來從給定的URL加載數據 $http.get('http://ionic-in-action-api.herokuapp.com/weather') //處理響應成功的狀況,並獲取返回天氣對象 .success(function(weather){ //把天氣數據賦值給$scope.weather模型 $scope.weather=weather; }) //在這裏作錯誤處理 .error(function(err){}); //用來把角度值轉換成風向的方法 $scope.getDirection = function(degree){ if(degree > 338){ degree = 360 - degree; } var index = Math.floor((degree+22)/45); return directions[index]; }; });
而後咱們來給添加視圖添加一個模板,建立文件www/views/weather/weather.html:
<ion-view view-title="天氣狀況"> <!-- 用容器包裹內容 --> <ion-content> <div class="list"> <!-- 添加列表元素,綁定天氣對象的數據 --> <div class="item">天氣:{{weather.weather[0].main}}</div> <div class="item">溫度:{{weather.main.temp}}°</div> <div class="item">空氣溼度:{{weather.main.humidity}}%</div> <div class="item">最高氣溫:{{weather.main.temp_max}}°</div> <div class="item">最低氣溫:{{weather.main.temp_min}}°</div> <div class="item"> <!-- 風向元素有兩個綁定數據,第二個會調用做用域中的第一個方法 --> 風向:{{weather.wind.speed}}mph,{{getDirection(weather.wind.deg)}} </div> </div> </ion-content> </ion-view>
而後咱們來聲明天氣視圖狀態,打開app.js文件,在預訂視圖下面添加以下代碼:
//聲明天氣視圖狀態 .state('weather',{ //給聲明的狀態添加URL、控制器和模板值 url:'/weather', controller:'WeatherController', templateUrl:'views/weather/weather.html' });
如今咱們運行一下吧,預覽結果以下圖:
此時當咱們執行應用的時候,會發現視圖會有一個加載過程,頁面數據會出現一個短暫的空白時期,知道數據加載完畢,這樣的用戶體驗並不理想,因此咱們須要加載一個載入指示器。可是在展現加載動畫的時候用戶沒法操做應用,因此要考慮清楚是否要這樣作。如今咱們先來實現一下如何加載動畫。
加載組件有兩個方法:show()和hide()。咱們須要在HTTP請求執行時顯示加載指示器,在響應返回後隱藏它。下面咱們打開weather.js文件,作以下修改:
//引用angular模塊 angular.module('starter') //聲明控制器並注入$scope和$http服務,把$ionicLoading服務注入控制器中 .controller('WeatherController', function($scope, $http, $ionicLoading){ //聲明包含全部可能風向的數組 var directions = ['北','東北','東','東南','南','西南','西','西北']; //在HTTP請求開始以前顯示加載組件 $ionicLoading.show(); //發起HTTP請求來從給定的URL加載數據 $http.get('http://ionic-in-action-api.herokuapp.com/weather') //處理響應成功的狀況,並獲取返回天氣對象 .success(function(weather){ //把天氣數據賦值給$scope.weather模型 $scope.weather=weather; //若是響應成功,隱藏加載組件 $ionicLoading.hide(); }) //在這裏作錯誤處理 .error(function(err){ //若是出錯,使用加載器來顯示錯誤信息並在三秒後自動關閉 $ionicLoading.show({ template:'沒法加載天氣,請稍候再試', duration:3000 }); }); //用來把角度值轉換成風向的方法 $scope.getDirection = function(degree){ if(degree > 338){ degree = 360 - degree; } var index = Math.floor((degree+22)/45); return directions[index]; }; });
4.6 在餐館視圖中使用卡片和無限滾動
下面咱們進入景點視圖的製做。咱們須要顯示一些本地的餐館共遊客參考,要實現這個功能,須要從外部加載餐館數據,並使用卡片組件來展現每一個餐館的名字和圖片,同時使用無限滾動這樣用戶滾動到列表底部時會加載更多的信息。
首先咱們先來構建餐館視圖的模板文件,新建文件www/views/restaurants/restaurants.html:
<ion-view view-title="附近餐館"> <ion-content> <!-- 建立卡片列表,使用ngRepeat遍歷餐館 --> <div class="list card" ng-repeat="restaurant in restaurants"> <div class="item"> <h2>{{restaurant.name}}</h2> <p>{{restaurant.address}},{{restaurant.city}}</p> </div> <div class="item item-image"> <img ng-src="{{restaurant.image_url}}" /> </div> </div> <!-- 無限滾動元素會在快要滑到底部的時候調用getRestaurants(),除非已經沒有新數據了 --> <ion-infinite-scroll on-infinite="getRestaurants()" ng-if="total > page" immediate-check="false"> </ion-infinite-scroll> </ion-content> </ion-view>
而後咱們須要給餐館視圖添加一個控制器。這個控制器須要加載餐館數據並在新數據加載完畢時通知唔想滾動組件隱藏。建立文件www/views/restaurant/restaurant.js:
angular.module('starter') //建立控制器並注入服務 .controller('RestaurantsController', function($scope, $http) { //建立一些視圖的做用域變量 $scope.page = 0; $scope.total = 1; $scope.restaurants = []; //定義加載餐館的方法 $scope.getRestaurants = function() { //遞增頁數併發起HTTP請求 $scope.page++; $http.get('http://ionic-in-action-api.herokuapp.com/restaurants?page=' + $scope.page).success(function(response) { //獲取餐館列表並把它們添加到ngRepeat操做的餐館數組中 angular.forEach(response.restaurants, function(restaurant) { $scope.restaurants.push(restaurant); }); //基於API的值更新總頁數 $scope.total = response.totalPages; //廣播事件,告訴無限滾動組件已經加載完成了 $scope.$broadcast('scroll.infiniteScrollComplete'); //處理錯誤,廣播事件並打印出錯誤報告 }).error(function(err) { $scope.$broadcast('scroll.infiniteScrollComplete'); console.log(err); }); }; //載入頁面的時候從API加載第一頁餐館數據 $scope.getRestaurants(); });
最後,在app.js文件中把視圖添加到狀態中:
.state('restaurants', { url:'/restaurants', controller:'RestaurantsController', templateUrl:'views/restaurants/restaurants.html' });
咱們來預覽一下效果:
4.7 使用幻燈片組件來實現應用介紹
咱們但願用戶在第一次使用咱們的旅遊應用時能看到一個快速入門的幻燈片介紹。$ionSlideBoxDelegate服務能夠用來在程序中控制幻燈片。大多數狀況下,咱們只須要一些HTML標籤就能夠展現幻燈片組件。新建文件www/views/tour/tour.html:
<ion-view view-title="旅遊啦" id="tour-view"> <ion-nav-buttons side="right"> <a class="button button-clear" href="#/home" nav-clear>goin</a> </ion-nav-buttons> <ion-slide-box show-pager="true"> <ion-slide> <span class="icon icon-slide ion-document-text"></span> <h3>查看預訂信息</h3> </ion-slide> <ion-slide> <span class="icon icon-slide ion-fork"></span> <h3>查看附近餐館</h3> </ion-slide> <ion-slide> <span class="icon icon-slide ion-ios-sunny"></span> <h3>查看本地天氣</h3> </ion-slide> </ion-slide-box> </ion-view>
而後咱們稍微修改一下幻燈片視圖的樣式,新建文件www/views/tour/tour.css:
#tour-view .slider{ height: 100%; } #tour-view .slider-slide{ padding-top:100px; text-align: center; } #tour-view .icon-slide{ font-size: 20em; display: inline-block; }
把tour.css引入index.html文件中:
<link href="views/tour/tour.css" rel="stylesheet">
最後咱們來把幻燈片視圖添加到應用的狀態中去,打開app.js文件,添加新狀態:
.state('tour',{ url:'/tour', templateUrl:'views/tour/tour.html' });
如今預覽一下咱們的應用吧~