JSBridge 是广为流行的Hybrid 开发中JS和Native一种通信方式,简单的说,JSBridge就是定义Native和JS的通信,Native只通过一个固定的桥对象调用JS,JS也只通过固定的桥对象调用native
JSBridge的基本原理
h5
➡️ 通过某种方式触发一个url
➡️ native捕获到url,进行分析
➡️ 原生做处理
➡️ native 调用h5的JSBridge对象传递回调
使用JSBridge的原因
传统的情况下:js可以和native之间通过api注入的方式实现相互通信,但JSBridge的出现还有下面原因:
- android4.2 以下,
addJavaScriptInterface
方式有安全漏洞 - ios7以下,js无法调用native
- url scheme交互方式是一套现有的成熟方案,可以兼容各种版本
实现JSBridge
实现一个JSBridge的方法:
- 设计出一个native与js交互的
全局桥对象
- js调用native
- native得知api被调用
- 分析 url 参数和回调的格式
- native调用js
- h5中api方法的注册以及格式
具体和JS侧相关的是前两个部分
一、设计native和js交互的全局对象
// 名称: JSBridge 挂在 window上的一个属性
var JSBridge = window.JSBridge || (window.JSBridge = {});
/**
该对象有如下方法:
registerHandler(String, Function) 注册本地 js 方法,注册后 native可通过 JSBridge调用,注册后会将方法注册到本地变量 messageHandles中
sendHandler(String, JSON, Function) h5 调用原生开放的api,调用后实际上还是本地通过 url scheme触发,调用时会将回调 id 存放到本地变量responseCallbacks 中
_handleMessageFromNative h5 调用native之后的回调通知
参数为 {reposeId: 回调id, responseData: 回调数据}
*/
var JSBridge = {
// 注册本地方法供原生调用
registerHandler: function(method, cb) {
// 会将cb 放入 messageHandlers里面,待原生调用
},
messageHandles: {}, // h5注册方法集合,供native通知后回调调用
// h5 主动调用native,需生成唯一的callbackId
sendHandler: function(mathod, data, succCb, errCb) {
// 内部通过iframe src url scheme 向native发送请求
// 并将对应的回调注册进 responseCallbacks
// native 处理结束后将结果信息通知到h5 通过 _handleMessageFromNative
// h5 拿到返回信息处理 responseCallbacks 里对应的回调
},
responseCallbacks: {}, // 回调集合
// native 通知 h5
_handleMessageFromNative: function(message) {
// 解析 message,然后根据通知类型执行 messageHandles 或 responseCallbacks里的回调
}
}
/**
注意:
1. native 调用_handleMessageFromNative通知h5,参数为 json 字符串
2. native 主动调用h5方法时 {methodName: api名, data, callbackId}
methodName: 开放api的名称
data: 原生处理后传递给 h5 参数
需要把回调函数的值 return 出去,供native拿到,
或者再发一个 bridge 回去,方法名是 methodNameSuccess,或者严禁掉,方法名为native生产的callbackId
*/
如:
bridge.register("hupu.ui.datatabupdate", (name) => {
if(name) {
// 再发一个bridge通知原生tab更新成功,,,method 可以为native生成的 callbackId
bridge.send('hupu.ui.datatabsuccess', {})
}
});
二、js调用native
方式:通过原生的setHandler
方法调用原生
// sendHandler 执行步骤
1. 判断是否有回调函数,如果有,生成一个回调函数id,并将id,和对应的回调添加放入回调函数集合 responseCallbacks 中
2. 通过特定的参数转换方法,将传入的数据,方法名一起拼接成一个 url scheme,如下:
var param = {
method: 'methodName',
data: {xx: 'xx'},
success: 'successId',
error: 'errorId'
}
// 变成字符串并编码
var url = scheme://ecape(JSON.stringify(param))
3. 使用内部创建好的iframe来触发scheme(location.href = 可能会造成跳转问题)
...创建iframe
var iframe = document.createElment('iframe');
iframe.src = url;
document.head.appendChild(iframe);
setTimeout(() => document.head.removeChild('iframe'), 200)