有时候朋友问我是做什么的?我说以前是用PHP写后台,最近是用H5写前台APP(俗称的Hybrid App);
在公司做了几个H5的项目之后,有时候也想抽空研究下H5写一些APP;总觉得写APP的开发更加有底气。尽管我偶尔有空也会研究下android,swift(Objective-C实在是难懂,没兴趣深入研究),也希望H5能开发一些不错的APP;
国内有包括APPCan等公司慢慢在发力,是很不错的趋势;由于mac上面无法使用APPCAN,所以我就没继续研究了,就看国外是怎么的一个过程;偶尔的机会发现了有人用ionic+angularjs+phonegap,很不错的尝试;于是我也想摸索下;

结论:使用上述的方法开发app,是可行的,至少我再android+IOS上面打包是成功了,体验还可以,开发比较方便,基于一些现成的组件;能在1~2天开发一个简单的demo;效率比较高,不过你需要对angularjs有一定的熟悉和了解;H5也一样;所以我也是慢慢学习慢慢研究;

入门必须:
(1) 看一遍ionic的文档,http://ionicframework.com/;
Ionic 是一个用HTML,CSS 跟JS 开发的一个用于移动设备的web app 开发框架,采用 Sass与AngularJS 开发。

(2) 看一遍phonegap的文档;目前phonegap又取名为cordova;有些常用的命令总结如下:

项目例子:http://my.oschina.net/nosand/blog/294011
ionic:
Create hybrid mobile apps with the web technologies you love.
Free and open source,Ionic offers a library of mobile-optimized HTML,
CSS and JS components,gestures,and tools for building highly interactive apps.
Built with Sass and optimized for AngularJS.

Qunee有一个上海地铁图的例子,有客户希望转成mobile app,考察过android的webview,以及PhoneGap等多种Hybrid App方案后,最后选择使用ionic,准确的说是ionic + PhoneGap + Qunee ionic是一种基于HTML5创建Hybrid应用的前端框架,借助phoneGap + angularJS实现一套跨平台,轻量的移动UI方案,本文将介绍借助ionic实现移动版Qunee上海地图的示例
背景知识

安装ionic所需软件环境 – java,android sdk等

ionic实际上是集大成者,借助了多种技术,自身是一套UI框架,结合PhoneGap实现跨平台移动APP,需要先安装好依赖的程序,比如nodejs,java,ADT,ant,xcode等,并设置好java_home,添加android sdk tool到环境变量

mac os x下安装ant

brew update
brew install ant
#mac osx 下,打开.bash_profile文件
cd~
open.bash_profile
#设置相关的Path,mac os x下增加类似下面的内容
exportJAVA_HOME=/usr/libexec/java_home-v1.8

# android
export PATH=${PATH}:/Users/macbook/WorkSpace/android-sdk-macosx/platform-tools:/Users/macbook/WorkSpace/android-sdk-macosx/tools

安装ionic和cordova

需要首先安装好nodejs,然后通过npm来安装

npm install -g cordova ionic
更多请参考官方文档+google http://ionicframework.com/getting-started/
创建ionic项目q-metro

使用下面的命令创建一个新的项目
ionic start q-metro
初始目录结构如下

<!DOCTYPE html> <html> <head> <Meta charset="utf-8"> name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no,width=device-width"<title></title> <link href="http://www.webdoes.com/archives/lib/ionic/css/ionic.css" rel="stylesheet""http://www.webdoes.com/archives/css/style.css" > <!-- IF using Sass (run gulp sass first),then uncomment below and remove the CSS includes above <link href="http://www.webdoes.com/archives/css/ionic.app.css" rel="stylesheet"> --> <!-- ionic/angularjs js --> <script src="http://www.webdoes.com/archives/lib/ionic/js/ionic.bundle.js"></script> <!-- cordova script (this will be a 404 during development) --> "http://www.webdoes.com/archives/cordova.js"></script> <!-- your app's js --> "http://www.webdoes.com/archives/js/app.js"></script> </head> <body ng-app="app" ng-controller="Metro" animation="slide-left-right-ios7"<ion-header-bar class="bar-dark"<h1 "title">{{title}}</h1> </ion-header-bar> <ion-content scroll="false"<div id="canvas" style="width: 100%; height: 100%;"></div> </ion-content> </body> "http://www.webdoes.com/archives/lib/qunee/qunee-min.js"</html>

index.html结构

首先看index.html,是主页面,里面引入了angularjs, cordova等js支持,此外还有app.js,controllers.js,services.js三个文件,这三个文件构建了app的应用逻辑,app是主程序,包含一些设置和启动脚本,services是数据支持部分,也就是model部分,用于提供数据的增删改查操作,controllers用于控制,包含业务逻辑控制代码

先在桌面环境下测试,Chrome运行正常,然后编译成各种移动平台版本,这里以android版本为例
ionic start q-metro
cd q-metro
ionic platform add android
ionic build android
ionic run android
如果要在虚拟机中测试,可以改用
ionic emulate android
ionic支持多种移动平台,如果希望创建ios可以将”android”改成”ios” 下面是android设备上真机运行界面如下:

给大家看看一个简单的demo的效果:

源码如下也很简单,供大家学习:

index.html如下:

<html "ionicApp"<title>Ionic-AngularJS Kitchen Sink</title> <!--<link href="http://code.ionicframework.com/1.0.0-beta.1/css/ionic.min.css" rel="stylesheet">--> <!--<script src="http://code.ionicframework.com/1.0.0-beta.1/js/ionic.bundle.min.js"></script>--> "http://www.webdoes.com/archives/lib/ionic/css/ionic.beta.min.css" "http://www.webdoes.com/archives/lib/ionic/js/ionic.bundle.beta.min.js"<style> .Box {height:300px;padding: 10px} </style> "AppCtrl"<ion-nav-bar "nav-title-slide-ios7 bar-positive"<ion-nav-back-button "button-icon ion-arrow-left-c"</ion-nav-back-button> </ion-nav-bar> <ion-nav-view "slide-left-right"></ion-nav-view> "menu.html" type="text/ng-template"> <ion-side-menus> <ion-side-menu side="left"> <ion-header-bar class="bar-positive"> <h1 "title">Side Menu</h1> </ion-header-bar> <ion-content> <ul "list"> <a href="http://www.webdoes.com/archives/609.html#/menu/tab/buttons" "item" menu-toggle="left">问答服务</a> <!--<a href="http://www.webdoes.com/archives/609.html#/menu/keyboard" "left">Keyboard Input Types</a>--> <!--<a href="http://www.webdoes.com/archives/609.html#/menu/slideBox" Slide Box</a>--> <a href="http://www.webdoes.com/archives/609.html#/menu/about" About</a> </ul> </ion-content> </ion-side-menu> <ion-side-menu-content> <ion-nav-view name="menuContent"></ion-nav-view> </ion-side-menu-content> </ion-side-menus> </script> "tabs.html" > <ion-nav-bar "bar-positive"> <ion-nav-back-button "button-icon ion-arrow-left-c"> </ion-nav-back-button> <ion-nav-buttons side="left"> <button "button button-icon button-clear ion-navicon" ng-click="toggleLeft()"></button> </ion-nav-buttons> <ion-nav-buttons side="right"> <button "button button-icon button-clear ion-compose" ng-click="modal.show()"></button> </ion-nav-buttons> </ion-nav-bar> <ion-tabs "tabs-icon-top tabs-positive"> <ion-tab title="问答" icon="ion-pricetag" href="http://www.webdoes.com/archives/609.html#/menu/tab/buttons"> <ion-nav-view name="buttons-tab"></ion-nav-view> </ion-tab> <ion-tab title="日记" icon="ion-clipboard" href="http://www.webdoes.com/archives/609.html#/menu/tab/list"> <ion-nav-view name="list-tab"></ion-nav-view> </ion-tab> <ion-tab title="健康汇" icon="ion-settings" href="http://www.webdoes.com/archives/609.html#/menu/tab/form"> <ion-nav-view name="form-tab"></ion-nav-view> </ion-tab> </ion-tabs> "buttons.html" > <ion-view title="大咖问答"> <ion-content "padding"> <div "head" style="background-image: url(img/headImg.jpg);background-size: cover;position:relative;height: 120px;"> </div> <div "item item-divider"> 问答集锦 </div> <ion-list> <ion-item ng-repeat="testItem in testItems" item="testItem" href="http://www.webdoes.com/archives/609.html#/menu/tab/testItem" data-id="{{testItem.id}}"> 问题标题: {{ testItem.title }} </ion-item> </ion-list> </ion-content> </ion-view> "item.html" "Item"> <ion-content "padding"> <p>内容暂时没提供</p> </ion-content> </ion-view> "testItem.html" "testItem"> <ion-content "list.html" "日记列表"> <ion-content> <ion-list show-delete="data.showDelete" on-"onItemDelete(item)" option-buttons="itemButtons"> <div "list"> <!--<div "item item-divider">--> <ion-item ng-repeat="item in items" item="item" href="http://www.webdoes.com/archives/609.html#/menu/tab/item"> Item {{ item.id }} </ion-item> </div> </ion-list> </ion-content> </ion-view> "form.html" "健康专栏"> <ion-content "padding"> 开发中,尽请期待... <br> </ion-content> </ion-view> "slideBox.html" > <ion-view> <ion-header-bar "bar-positive"> <button "toggleLeft()"></button> <h1 Box</h1> </ion-header-bar> <ion-content> <ion-slide-Box> <ion-slide> <div "Box"> <h2>Box #1</h2> <p>Content goes here</p> </div> </ion-slide> <ion-slide> <div 2</h2> <p>3</h2> <p>Content goes here</p> </div> </ion-slide> </ion-slide-Box> </ion-content> </ion-view> "keyboard.html" Input</h1> </ion-header-bar> <ion-content "list"> <label "item item-divider"> Input types for popup keyboard </label> <label "item item-input"> <span "input-label">Text</span> <input type="text" ng-model="user.username"> </label> <label Password</span> <input type="password" ng-model="user.password"> </label> <label Email</span> <input type="email"> </label> <label Tel</span> <input type="tel"> </label> <label Number</span> <input type="number"> </label> <label Date</span> <input type="date"> </label> <label Month</span> <input type="month"> </label> </div> </ion-content> </ion-view> "about.html" About</h1> </ion-header-bar> <ion-content "card"> <div "item"> <h3>本测试demo由徐杰开发设计,仅供参考</h3> <p><a href="http://www.webdoes.com" target="_blank">联系他</a></p> </div> </div> </ion-content> </ion-view> "modal.html" > <div "modal"> <ion-header-bar "bar bar-header bar-positive"> <h1 "title">咨询</h1> <button "button button-clear button-primary" ng-click="modal.hide()">取消</button> </ion-header-bar> <ion-content "input-label">标题</span> <input type="text"> </label> <label "input-label">内容</span> <textarea rows="4"></textarea> </label> </div> <button "button icon icon-right ion-arrow-right-c button-balanced button-block">提交</button> </ion-content> </div>  核心代码app.js如下: 
angular.module('ionicApp', ['ionic']) .config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('menu', { url: "/menu", abstract: true, templateUrl: "menu.html", controller: 'MenuCtrl' }) .state('menu.tabs',0)">"/tab", views: { 'menuContent' :{ templateUrl: "tabs.html" } } }) .state('menu.tabs.buttons',0)">"/buttons",0)">'buttons-tab': { templateUrl: "buttons.html",0)">'ButtonsTabCtrl' } } }) .state('menu.tabs.list',0)">"/list",0)">'list-tab': { templateUrl: "list.html",0)">'ListCtrl' } } }) .state('menu.tabs.item',0)">"/item",0)">"item.html" } } }) .state('menu.tabs.testItem',0)">"/testItem",0)">"testItem.html" } } }) .state('menu.tabs.form',0)">"/form",0)">'form-tab': { templateUrl: "form.html" } } }) .state('menu.keyboard',0)">"/keyboard",0)">'menuContent': { templateUrl: "keyboard.html" } } }) .state('menu.slideBox',0)">"/slideBox",0)">"slideBox.html",0)">'SlideBoxCtrl' } } }) .state('menu.about',0)">"/about",0)">"about.html" } } }); $urlRouterProvider.otherwise("menu/tab/buttons"); }) .controller('ListCtrl',139)">function ($scope) { $scope.data = { showDelete: false }; $scope.itemButtons = [ { text: 'Delete', type: 'button-assertive', onTap: function (item) { alert('Delete Item: ' + item.id + ' ?'); } } ]; $scope.onItemDelete = function (item) { $scope.items.splice($scope.items.indexOf(item), 1); }; $scope.items = [ { id: 1, title:'慢性鼻炎怎么预防?' }, { id: 2,0)">'高血压如何预防?' },0)">3,0)">'冠心病如何有效治疗?' },0)">4,0)">'高血压如何预防?' } ]; }) .controller('ButtonsTabCtrl',139)">function ($scope, $ionicPopup, $ionicActionSheet, $ionicModal) { $scope.showPopup = function () { $ionicPopup.alert({ title: 'Popup', content: 'This is ionic popup alert!' }); }; $scope.showActionsheet = function () { $ionicActionSheet.show({ titleText: 'Ionic ActionSheet', buttons: [ { text: 'Facebook' }, { text: 'Twitter' }, ], destructiveText:  cancelText: 'Cancel', cancel: function () { console.log('CANCELLED'); }, buttonClicked: function (index) { console.log('BUTTON CLICKED', index); return true; }, destructiveButtonClicked: 'DESTRUCT'); true; } }); }; $scope.testItems = [ { id: '高血压如何预防?' } ]; $ionicModal.fromTemplateUrl('modal.html',139)">function (modal) { $scope.modal = modal; }, { animation: 'slide-in-up' }); }) .controller('SlideBoxCtrl',139)">function($scope, $ionicslideBoxDelegate) { $scope.nextSlide = function() { $ionicslideBoxDelegate.next(); } }) .controller('MenuCtrl', $ionicSideMenuDelegate, $ionicModal) { $scope.toggleLeft = function() { $ionicSideMenuDelegate.toggleLeft(); }; $ionicModal.fromTemplateUrl('AppCtrl',139)">function() { ionic.Platform.ready(function() { }); });

发布:

Now we can tell cordova to generate our release build:

$ cordova build--release android

在IOS中也是一样,不过IOS要打包成ipa,需要开发者账号,有兴趣朋友求提供下,谢谢!

使用ionic+angular+phonegap开发APP入门的更多相关文章

  1. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  2. 利用Node实现HTML5离线存储的方法

    这篇文章主要介绍了利用Node实现HTML5离线存储的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. 详解如何通过H5(浏览器/WebView/其他)唤起本地app

    这篇文章主要介绍了详解如何通过H5(浏览器/WebView/其他)唤起本地app的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. H5混合开发app如何升级的方法

    本篇文章主要介绍了H5混合开发app如何升级的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. AmazeUI 折叠面板的实现代码

    这篇文章主要介绍了AmazeUI 折叠面板的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas的示例代码

    这篇文章主要介绍了AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  7. HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码

    这篇文章主要介绍了HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  8. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  9. html5唤起app的方法

    这篇文章主要介绍了html5唤起app的方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. HTML5拍照和摄像机功能实战详解

    这篇文章主要介绍了HTML5拍照和摄像机功能实战详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部