进入正题ionic之前,先聊聊目前很火的h5开发移动应用的主流技术,做个对比。
ionic是一个专注于用WEB开发技术,基于HTML5创建类似于手机平台原生应用的一个开发框架。绑定了AngularJS和Sass。这个框架的目的是从web的角度开发手机应用,基于PhoneGap的编译平台,可以实现编译成各个平台的应用程序。
ionic提供很多css组件和javascript UI库。
ionic可以支持定制android和ios的插件,也支持服务端REST的敏捷开发。
ionic 特点:
1.ionic 基于Angular语法,简单易学。
2.ionic 是一个轻量级框架。
3.ionic 完美的融合下一代移动框架,支持 Angularjs 的特性, MVC ,代码易维护。
4.ionic 提供了漂亮的设计,通过 SASS 构建应用程序,它提供了很多 UI 组件来帮助开发者开发强大的应用。
5.ionic 专注原生,让你看不出混合应用和原生的区别
6.ionic 提供了强大的命令行工具。
7.ionic 性能优越,运行速度快。
ionic优点
学习成本低
对前端开发者来说,学习成本不是很高,如果有接触过 angular ,就几乎没有什么学习成本了
简单易用
强大的CLI, start -> platform -> serve -> build -> emulate -> run ,全套服务命令行完成,不用写配置文件,不用F5
组件多而强大
提供了很多强大的现成组件,很容易实现流行的交互效果,比如下拉刷新( ion-refresher )、上拉加载/瀑布流( ion-infinite-scroll )、tabs( ion-tabs )、侧边栏菜单( ion-side-menu )等等,只需要写一点点代码,就能实现这些流行效果,比native开发速度快太多了
支持cordova插件
打开了这扇门,意味着我们可以使用大量的原生功能,比如调用相机拍照、响应返回按钮、打电话发短信发邮件……都只要几行代码就能搞定
更新速度快
快速更新意味着有人维护,bug能被迅速修复
缺点:
新版本不完全向后兼容
bug难以定位
angular+cordova+ionic+javascript,发现问题后,很难确定是哪块的问题
性能优化难
动画卡顿,低端机体验更差,而优化措施一般都是建议少用动画少用阴影少用渐变
1创建应用:
进入想要创建工程的目录,输入命令:
a. 创建空白应用:
$ ionic start myApp blank
b. 使用ionic官方提供的模版,创建一个带标签的应用:
$ ionic start myApp tabs
c. 使用ionic官方提供的模版,创建一个带侧边栏菜单的应用:
$ ionic start myApp sidemenu
2.运行
1.ios:
$ cd myApp
$ ionic platform add ios
$ ionic build ios
$ ionic emulate ios
2.android:
$ cd myApp
$ ionic platform add android
$ ionic build android
$ ionic emulate android
如果是使用手机或者genymotion的话,最后一行命令是:ionic run android
,建议使用使用手机或者genymotion模拟器测试,比AS的模拟器快很多。
3.通过Chrome浏览器运行调试
进入工程目录,输入命令:
$ ionic serve
在Chrome浏览器打开调试地址,将浏览器跳到手机模式,可以方便快捷的测试android和ios下的运行情况,一般功能的调试推荐用这种方式。
一.jsonp跨域,php服务怎么写
这是angular的问题angular的$http可以发送jsonp请求,用法类似于jQuery,如下:
// 请求数据
$http.jsonp(sUrl).success(function(res){
// ...
}).error(function(err){
// ...
});
sUrl 有特殊要求,必须带上 callback 参数,而且参数值 只能 是 JSON_CALLBACK ,angular文档:
Relative or absolute URL specifying the destination of the request. The name of the callback should be the string JSON_CALLBACK.
例如:
var sUrl = http://www.ayqy.net/app/rsshelper/index.php?callback=JSON_CALLBACK
而问题是:php服务怎么写?直接返回用 JSON_CALLBACK() 包裹的json数据?
不对,因为真正请求的url中 callback !== JSON_CALLBACK ,被angular 偷偷 (文档没有说明)替换掉了,所以后台需要这样写:
if (strpos($_SERVER["REQUEST_URI"], 'callback')) {
$res = json_encode($res);
// echo $_SERVER["REQUEST_URI"];
// /angular/test/http/main.php?callback=angular.callbacks._0
// $res = 'JSON_CALLBACK('.$res.')';
// 错的
$res = $_GET['callback'].'('.$res.')';
}
?>
当然,这是get的情况,比较简单,如果是post,还需要通过别的方式取 callback ,完整例子如下:
// get
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$res = '{';
// arg
if (isset($_GET['arg'])) {
$res .= '"arg": "'.$_GET['arg'].'", ';
}
// method
if (strpos($_SERVER["REQUEST_URI"], 'callback')) {
// echo $_SERVER["REQUEST_URI"];
// /angular/test/http/main.php?callback=angular.callbacks._0
$res .= '"arg": "'.$_GET['arg'].'", ';
$res .= '"method": "jsonp"}';
// $res = 'JSON_CALLBACK('.$res.')';
// 错的
$res = $_GET['callback'].'('.$res.')';
}
else {
$res .= '"method": "get"}';
}
echo $res;
}
// post
else if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 直接拿拿不到,因为传过来的是json串
// echo $_POST['arg'];
$jsonArg = file_get_contents('php://input');
if (isset($jsonArg)) {
echo substr($jsonArg, 0, strlen($jsonArg) - 1).', "method": "post"}';
}
else {
echo '{"method": "post"}';
}
}
?>
二.ion-content的阻尼回弹效果没了
ionic v1.2取消了 ion-content 默认的阻尼回弹效果,明明一模一样的代码,就是没有回弹效果,后来发现是版本更新的锅,翻了很久后,在 官方博客 的 评论 里找到了答案:
Great news, thank you! It seems that the “has-bouncing=’true’” does not work with the native scroll, is it correct? I managed though to have it again by going to back go js scroll (overflow-scroll=”false”)
I only checked in the browser so if any one can confirm that with native scrolling removes bouncing that would be great.
I need this feature for a custom ‘pull refresh’ method I had.
也就是说,v1.2之后想要有阻尼回弹效果,需要这么做:
<ion-content overflow-scroll="false" has-bouncing="true"></ion-content>
三.多个view之间的数据共享
也就是多个controller之间的数据共享(一般不同view对应不同controller)问题,当然,最简单的方法是用全局变量( $rootScope ),但这样不好,更合理的方式是自己写个 service 或者 factory ,提供数据存取接口,在需要的地方依赖注入即可,比如:
.service('DataServ', ['$http', 'UIServ', function($http, UIServ) {
// ...
// 字典
var oDir = {
// key: value
};
function save(val) {
var sKey = Date.now() + '';
oDir[sKey] = val;
return sKey;
}
function get(sKey) {
return oDir[sKey];
}
return {
// ...
save: save,
get: get
};
}]);
然后通过url传递 sKey 即可实现数据共享,很干净
四.通知视图更新
在模板中写好了数据展示,但如果打开页面后数据还没到,模板解析完了,由于没有数据显示空白页,过了一会儿数据到了,发现视图没有更新,仍然是一片空白,比如:
{{data}}
// js
app.controller('MainCtrl', ['$scope', 'DataServ', function($scope, DataServ) {
// ...
setTimeout(function() {
// ...
$scope.data = 'data';
})
}]);
因为给data赋值的操作跑到了controller作用域外,此时需要手动通知视图更新,如下:
// ...
$scope.data = 'data';
$scope.$apply();
当然,一般不需要手动通知,即便是异步返回的数据,因为这里只与作用域有关,总之,如果发现视图需要手动更新,添上 $apply 就好了
五.php原生xml扩展如何获取 里的内容
rss格式中会有 标签,直接取 content 取不到,需要特殊的方式:
$content = (string)$item->children("content", true);
// $encodedContent = $content->encoded;
// $content->encoded返回转义过的html,比如把&转成&,一般用于
直接展示
当然,前提是使用原生xml扩展( xml=simplexmlloadfile(url); )解析xml才会遇到这个问题
六.在浏览器中打开外部页面
需要使用一个cordova插件,cd进项目文件夹,然后:
ionic plugin add cordova-plugin-inappbrowser
安装完成后就可以调用了,不用修改配置文件,不用引入其他js,如下:
// openInBrowser
window.open(‘http://example.com’, ‘_system’); Loads in the system browser
window.open(‘http://example.com’, ‘_blank’); Loads in the InAppBrowser
window.open(‘http://example.com’, ‘_blank’, ‘location=no’); Loads in the InAppBrowser with no location bar
window.open(‘http://example.com’, ‘_self’); Loads in the Cordova web view
// test
window.open(url, '_system'); // 系统默认浏览器
// window.open(url, '_blank'); // 很丑的安卓内置浏览器
// window.open(url, '_self'); // 同上
一般都用 _system
七.splash screen黑屏白屏
黑屏白屏其实是同一个问题,但这个问题相当难解决
ionic默认集成了 splashscreen 插件,这个cordova插件效果不是很完美,默认配置只在首次打开app时显示splash screen,但实际效果是:
When the app starts the splash screen shows for a few seconds as expected, and then the screen goes black for @1 second and then white for @2 seconds and then the main app page appears.
Is there any way to prevent the black and white pages appearing? I read somewhere that a black page appears when there is no splash page but I do have a splash page and it appears fine.
在 stackoverflow 找到了这个问题描述,简直太贴切了,但是单靠问题下面的回答无法解决白屏问题,还需要改配置文件
最初发现的现象是黑屏(把上面英文描述里的white换成黑),后来找到了原因:主视图容器 ion-nav-view 是空的,而它的背景色是 #000 ,所以修复方法是给里面塞个 ion-view :
<ion-nav-view>
<ion-view>ion-view>
ion-nav-view>
或者添css,把 ion-nav-view 的背景色改成白色。但问题还没解决,黑屏问题变成白屏问题了,解决方案比较麻烦
把splashscreen插件降级到v2.0.0
v2.0.0之后的版本有bug,目前(2016/1/9)自带的版本是v3.0.0。先cd到项目文件夹,然后命令行:
// 删掉现有版本
cordova plugin rm cordova-plugin-inappbrowser
// 安装v2.0.0
cordova plugin add cordova-plugin-inappbrowser
改配置文件MyApp/config.xml
"SplashScreen" value="screen"/>
"AutoHideSplashScreen" value="false"/>
"auto-hide-splash-screen" value="false"/>
"ShowSplashScreenSpinner" value="false"/>
"SplashMaintainAspectRatio" value="true" />
"SplashShowOnlyFirstTime" value="false"/>
"SplashScreenDelay" value="10000"/>
取消自动隐藏(改为代码控制隐藏),把持续时间改为较大的值(10秒),设置每次打开应用都显示splash screen
P.S.默认只有 SplashScreen 和 SplashScreenDelay ,需要把其它的( SplashMaintainAspectRatio 可选)都添上
改app.js
手动隐藏splash screen,在run里面添上
.run(['$rootScope', function($rootScope) {
// init
// $rootScope.isLoading = false;
// hide splash immediately
if(navigator && navigator.splashscreen) {
navigator.splashscreen.hide();
}
});
}])
这样就好了,不要延时调用hide,否则仍然会出现白屏(有些解决方案要求$timeout 50毫秒hide,仍然会出现白屏,不要这样做)
最怨念的问题结束了,看似简单的功能,想要有 完美的原生体验 却很难,奇奇怪怪的问题很难解决,目前可行的解决方案可能过段时间就不行了。
八.安卓版本签名发布
各种签名方法都过时了,目前(2016/1/9)可以用的签名方法如下:
在MyApp\platforms\android创建keystore
具体步骤请查看: Ionic toturial for building a release.apk
创建release-signing.properties文件
build
cd到项目文件夹,然后命令行 ionic build –release android ,成功后会生成2个东西,在MyApp\platforms\android\build\outputs\apk下,分别是android-armv7-release.apk和android-x86-release.apk,一般平板和PC用x86,手机用arm7,如果要上传google play的话,2个都要传,下载时有自动识别
至于crosswalk,提供了chrome内核,能让低端机支持高端东西,但会让apk 变大很多 (3.5M->23M),添上crosswalk后变卡了,但为了支持低端机用户,一般都会添上crosswork。
未完待续…