简介:在本节课中,咱们将会经过一个虚构的旅游景点来构建一款功能完善的应用。本应用的核心特性是管理用户的应用内导航。本节课的主要目的,是展示构建一个完整的应用的过程。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' });
如今预览一下咱们的应用吧~