混合应用中的javascript实践
混合应用中的javascript实践
混合应用(hybird app) 在几年前便进入大众视野,近来更是越发风生水起,深受人民群众的喜爱。
目录
概念
什么是混合应用
混合应用(hybird app) 顾名思义,便是将web app与native app混合在一起,既享受html快速开发、快速版本迭代带来的便利,也能使用原生app调用系统接口和第三方SDK的强大扩展能力。
混合方式
如同茴字有几种写法一般,构建混合应用也有不同的方式。其中一种是主要使用静态html,用 phonegap 或 cordova 加壳的方式打包成app。另一种则是小部分webview直接引入服务端渲染的html,其他功能都是原生app开发。
其中前一种方式最为出名的解决方案便是使用 angular.js + cordova 的 ionic,而使用后一种方式的app则数不胜数。
但是无论使用哪一种方式,都面临一个问题,html和app的交互。html自己不会动起来,本文将浅谈javascript如何交互app和html。
交互
方法注入
常见的app和html交互有 使用url 和 互相调用方法 两种方式。
使用url 这种方式比较简单,通过 location.href = 'url' ,即可将方法和参数传递给app,但是无法传递复杂的数据。
互相调用方法 这种方式则较为复杂,除了需要app端写好调用的方法注入到 window 对象之外,还需要JavaScript暴露方法给app使用。以常见的评论交互为例:
// 点击“发表评论”,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 方法中提取而来的方法,根据手机系统不同,使用不同策略,例如:
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发起请求,示例:
// 不和谐: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 编码。
以上面的发表评论为例:
# 本段代码使用了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?。
资源加载
把资源加载放到交互里面,我也不知道合不合适。对于 第一种混合方式 来说,可以把更多的静态资源放到本地,然后通过app接口加载。对于第二种,更多的还是从服务端渲染并加载资源。
对于一些交互类的数据,而非资源,既可以选择存放在浏览器的localStorge中,也可以选择存放于app本地文件,这取决于哪一方进行操作运算了。
调试
html的移动端调试时很困难的,嵌入app的html调试更是难上加难。因为js和app的方法相互调用,任何一方出错,都会导致程序不按套路运行。
除了仔细的约定两端的方法和检查代码的错误外,还需要一个强力的工具。在这里推荐使用 vConsole ,可以比较直观的定位到错误。

其他
兼容性
html在app中的兼容性取决于app内嵌浏览器内核。iOS系统默认的浏览器是safari,而andriod系统默认的浏览器则五花八门。
如果选择系统默认浏览器作为内嵌浏览器的话,ios一般兼容性较好,能取得和PC端一致的效果。android机型则会比较悲剧,使用 crosswalk方案 或许是个正确的选择。
特性启用
在内嵌浏览器中,html5的某些特性默认是关闭的,比如 localStorge , 需要app端手动去开启。所以在开发中一定要做好可用性检测,减少出现bug的几率。
局部视图
当html作为webview的局部视图被加载时,由于app虽然可以获取到页面加载后的高度,但是无法获取动态改变后的高度,使得局部滚动失效。
所以在作为局部视图加载时,如果需要页面高度会根据比如评论,动画效果而发生改变的话,需要及时通知app更新webview高度。
混合应用中的javascript实践的更多相关文章
- Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用
前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...
- 在Swift中使用JavaScript的方法和技巧
本文作者Nate Cook是一位独立的Web及移动应用开发者,是继Mattt大神之后NSHipster的主要维护者,也是非常知名活跃的Swift博主,并且还是支持自动生成Swift在线文档的Swift ...
- HTML中的javascript交互
在Android开发中,越来越多的商业项目使用了Android原生控件与WebView进行混合开发,当然不仅仅就是显示一个WebView那么简单,有时候还需要本地Java代码与HTML中的javasc ...
- Hybrid混合开发中schema协议的使用与封装
混合开发中JS与APP通信的实现原理: JS通过schema协议,传递参数和全局回调函数给APP端 APP执行完(如微信扫一扫)后,调用协议中传入的回调函数,在前端执行回调处理. 默认写法: < ...
- 在 Swift 專案中使用 Javascript:編寫一個將 Markdown 轉為 HTML 的編輯器
原文:Using JavaScript in Swift Projects: Building a Markdown to HTML Editor 作者:GABRIEL THEODOROPOULOS ...
- JavaScript高级程序设计-(1)html中使用JavaScript
html中使用JavaScript 1.延迟脚本 script标签定义了defer属性,脚本会被延迟到整个页面都解析完毕后运行 详细内容如下: 2.异步脚本 script标签定义了async属性,as ...
- 在HTML中使用JavaScript元素
script属性<script async = async charset="utf-8" defer="defer" src="index.h ...
- 2在HTML中使用JavaScript
像HTML页面中插入JavaScrip的主要方法,就是使用<script>元素.HTML4.01为<script>定义了6个属性:async:可选,表示应该立即下载脚本,当不妨 ...
- javascript高级编程3第二章:在html中使用javascript
2.1 <script>元素 向html页面中插入javascript的主要方法,就是使用<script>元素.这个元素被加入到正式的html规范中.html4.01为< ...
随机推荐
- 尝试EJB整合Mybatis部署时报错:获得带有类加载器MybatisUtil的ModuleClassLoader的反射信息出错,请问大神如何解决
mybatis的配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configurati ...
- 常见面试第二题之什么是Context
今天的面试题,也就是我们常见面试题系列的第二题,我们来讲一讲android中的context.我相信大家android开发者一定对于这个context非常熟悉,肯定都有使用过,肯定没有没使用过的.但是 ...
- 百度地图 api 功能封装类 (ZMap.js) 新增管理事件功能 [源码下载]
ZMap 功能说明 ZMap.js 本类方法功能大多使用 prototype 原型 实现: 包含的功能有:轨迹回放,圈画区域可编辑,判断几个坐标是否在一个圆圈内,生活服务查询,从经纬度获取地址信息,地 ...
- 练习一_使用Git进行代码管理的心得
2015年9月19日,第一次软工实践课.助教给我们介绍了git,GitHub.显而易见,我并没有听懂.所以整个上午都在找教程,一个字一个字对着敲,然后敲着敲着就出错,回宿舍,继续敲,也是一样的... ...
- JQuery学习(1)
JQuery学前准备 JQuery的各种包: 1.jquery-ui(包含小工具及组件) 2.jquery-1.7.1.intellisense.js(智能提示包) 3.jquery-1.7.1.js ...
- webform中的验证控件及两个应用技巧
一.非空验证--RequiredFiledValidator <一>属性: ErrorMessage--验证出错后的提示信息 ControlToValidate--要验证的控件的ID Di ...
- 【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题
达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状 ...
- 读JS高级API笔记_(DOM&&DOM2&&DOM3)哎呀——园龄才9个月啊
---恢复内容开始--- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: ...
- web前端开发常用的10个高端CSS UI开源框架
web前端开发常用的10个高端CSS UI开源框架 随着人们对体验的极致追求,web页面设计也面临着新的挑战,不仅需要更人性化的设计理念,还需要设计出更酷炫的页面.作为web前端开发人员,运用开源 ...
- 【Gym 100971A】Treasure Island
题意 题目链接给你一个地图,'#'代表水,'.'代表陆地,'?'代表擦去的地图,可能是'#'也可能是'.'.地图中本该只有一块相连的陆地,若只有一种方案则输出确定的地图.若有多种方案,则输出‘Ambi ...