混合应用(hybird app)
在几年前便进入大众视野,近来更是愈加风生水起,深受人民群众的喜好。javascript
混合应用(hybird app)
顾名思义,即是将web app与native app混合在一块儿,既享受html快速开发、快速版本迭代带来的便利,也能使用原生app调用系统接口和第三方SDK的强大扩展能力。html
如同茴字有几种写法
通常,构建混合应用也有不一样的方式。其中一种是主要使用静态html,用 phonegap
或 cordova
加壳的方式打包成app。另外一种则是小部分webview直接引入服务端渲染的html,其余功能都是原生app开发。
其中前一种方式最为出名的解决方案即是使用 angular.js
+ cordova
的 ionic,而使用后一种方式的app则数不胜数。
可是不管使用哪种方式,都面临一个问题,html和app的交互。html本身不会动起来,本文将浅谈javascript如何交互app和html。html5
常见的app和html交互有 使用url
和 互相调用方法
两种方式。使用url
这种方式比较简单,经过 location.href = 'url'
,便可将方法和参数传递给app,可是没法传递复杂的数据。互相调用方法
这种方式则较为复杂,除了须要app端写好调用的方法注入到 window
对象以外,还须要JavaScript暴露方法给app使用。以常见的评论交互为例:java
// 点击“发表评论”,js须要调用app的评论框 $('.js-comment').click(function(){ window.appMethod.comment(); }); // app端在用户点击“发送”按钮时,再调用javascript的插入评论方法(我不会app开发,如下是伪代码) function comment(){ TEXTAREA.OPEN(); } SUBMIT_BUTTON.CLICK(function(){ NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"window.jsMethod.comment()"]; })
其中 window.appMethod
这个方法,是一个从 iOS 和 android 方法中提取而来的方法,根据手机系统不一样,使用不一样策略,例如:jquery
var window.appMethod = null; var androidMethod = { comment: function(){ window.android.comment(); } }; var iOSMethod = { comment: function(){ location.href = 'ios://comment?' } }; window.appMethod = iOS_DEVICE ? iOSMethod : androidMethod;
相比方法的注入点,策略处理,方法的调用时机更为重要。在js中调用一个不存在方法,会发生错误从而致使代码没法继续向下执行。
好比进入页面时,app须要告诉html一些登陆信息,以初始化点赞,收藏等组件。若是由app直接调用js方法去通知,那么极可能页面还没加载完,而发生上面提到的错误。
因此好的时机是让js主动去向app发起请求,示例:android
// 不和谐:app直接通知js更新用户登陆状态,可能会发生错误 eval('window.jsMethod.setUser();') // 和谐:js主动去向app发起请求 $(function(){ window.appMethod.getUser(); }) // app端在接收到getUser方法后,调用js方法(我不会app开发,如下是伪代码) function getUser(){ // 获取user状态,而后执行 NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"window.jsMethod.setUser()"]; }
以上的示例中的方法并无进行参数传递,是为了留到这里。
相比JavaScript,在android和iOS方法中传递参数显得极为严格,除了要指定参数个数,还要指定参数类型。
虽然能够经过数组的方式进行不定个数参数的传递,可是指定参数类型仍是挺烦人的。因此建议始终使用 String
类型做为参数进行传递,复杂的json格式参数使用 JSON.stringify
。使用url传递则须要对参数进行 encode 编码。
以上面的发表评论为例:ios
# 本段代码使用了jquery // js给app传参 var androidMethod = { comment: function(params){ window.android.comment( JSON.stringify(params) ); } }; var iOSMethod = { comment: function(params){ location.href = 'ios://comment?'+$.param(params) } }; ... ... $('.js-comment').click(function(){ var params = { "user_id": 30, "article_id": 958, "article_type": "news" }; window.appMethod.comment(params); }); // app给js传参 SUBMIT_BUTTON.CLICK(function(){ var params = { "comment_id": 5484, "comment_content": "我不会写app,姑且用js写伪代码" }; NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"window.jsMethod.comment( JSON.stringify(params) )"]; })
这里的方法监听指的是app对js方法的单向监听。
由于须要app监听的js方法,都是显示的调用了app方法,或是跳转到了一个url。调用app的方法自不待言,url的监听却有多种。
一种是a连接的 http
GET 请求的监听,多见于 下一篇文章
, 相关文章
等跳转页面的方法。通常来讲不用带参数。还有一种是自定义的 schema
监听,使用这种方式通常是不带或带较少的参数,好比 myiOS://mymethod?
。git
把资源加载放到交互里面,我也不知道合不合适。对于 第一种混合方式 来讲,能够把更多的静态资源放到本地,而后经过app接口加载。对于第二种,更多的仍是从服务端渲染并加载资源。
对于一些交互类的数据,而非资源,既能够选择存放在浏览器的localStorge中,也能够选择存放于app本地文件,这取决于哪一方进行操做运算了。github
html的移动端调试时很困难的,嵌入app的html调试更是难上加难。由于js和app的方法相互调用,任何一方出错,都会致使程序不按套路运行。
除了仔细的约定两端的方法和检查代码的错误外,还须要一个强力的工具。在这里推荐使用 vConsole ,能够比较直观的定位到错误。web
vConsole 截图
html在app中的兼容性取决于app内嵌浏览器内核。iOS系统默认的浏览器是safari,而andriod系统默认的浏览器则五花八门。
若是选择系统默认浏览器做为内嵌浏览器的话,ios通常兼容性较好,能取得和PC端一致的效果。android机型则会比较悲剧,使用 crosswalk方案 或许是个正确的选择。
在内嵌浏览器中,html5的某些特性默认是关闭的,好比 localStorge
, 须要app端手动去开启。因此在开发中必定要作好可用性检测,减小出现bug的概率。
当html做为webview的局部视图被加载时,因为app虽然能够获取到页面加载后的高度,可是没法获取动态改变后的高度,使得局部滚动失效。因此在做为局部视图加载时,若是须要页面高度会根据好比评论,动画效果而发生改变的话,须要及时通知app更新webview高度。