初次开发hybrid H5的坑及方案
Mar 2, 2019
hybrid h5
hybrid 翻译为杂交, hyrid h5 是指将web前端页面嵌入到原生APP( iOS和Android )中的运行的方案。
相对于原生开发,web前端的开发发展时间更长、从业人员更多、生态更为繁荣,而且开发效率也更高。
但web并不能直接调用原生API,而且运行内存、调度也差与原生,流畅性就显得不足。
基于以上原因,协调开发资源,将一些展示性、交互不多的页面让web开发,嵌入原生Webview中运行,就可以大大提高APP开发效率,利用团队开发资源。
h5调用原生方法
参考 (https://github.com/marcuswestin/WebViewJavascriptBridge)
- 直接注入调用
iOS能访问Webview下全局对象window,所以可以将js方法挂载到window上,然后iOS调用;
安卓的话可以注入方法到window上,然后js调用这原生方法。 - 协议监听
原生API能拦截Webview的网络请求,url根据协议传参,原生解析后执行,将结果挂载到window上。
js的url实现方法:
2.1 window.location.href
2.2 利用页面中嵌套的iframe的url(将iframe的长宽都设为很小或者0,取到数据后再移除这个iframe)建议使用②iframe的方式,因为如果我们连续多次修改window.location.href的值,在Native层只能接收到最后一次请求,前面的请求都会被忽略掉。 - 引入JsBridge(安卓)和 WebViewJavascriptBridge(iOS)库的方案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// 安卓运行
// 如果WebViewJavascriptBridge已挂载,直接执行,否则,等待WebViewJavascriptBridgeReady时间触发,即原生方法已挂载后执行
if (window.WebViewJavascriptBridge) {
//do your work here
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
//do your work here
},
false
);
}
// iOS运行
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
此次项目,我们直接进行的注入调用。
h5中涉及到摄像头拍照的功能,由原生提供,注入到h5中,挂载到window.api上,js则可以直接调用方法。1
window.api.camera(params, function(){}) // 调用原生注入的API,参数不可缺少,传递params参数以及回调函数
html中引入一个固定名称的js文件供安卓注入,比如 android.js, 兼容安卓5,文件不能为空,所以可以声明一个无关紧要的变量或者console。
兼容遇到的问题
- 安卓5下需要对Promise reject进行处理,否在抛错
- es6 spread语法, …obj, 低版本下需要确定obj为Object,如果为’’,会抛错
- iOS调用js方法时,内部不能有Promise,否则会卡死,不执行回调
- 用iframe时,iOS会需要src同源,否则会解析失败
- iOS input输入框,需要父元素position不是static,或者input{transform:translateZ(0)}