一、什么是Javascript bridge?
在web和native之间进行交互,如传递数据,调用函数,而连接web与native需要一个桥梁,通常称为javascript bridge
目前github上开源最广的WebViewJavascriptBridge
、JsBridge
、DSBridge
。
二、DSBridge
DSBridge特性
- 官方同时支持ios和android。
- 不仅支持异步调用,还支持同步调用(DSbridge是唯一一个支持同步调用的javascript bridge)。
- 三端友好,在接口易用性比
WebViewJavascriptBridge
强
三、DSBridge的内部原理
1、iOS原生端
初始化的时候,注入
window._dswk=true;
,标记为是Native使用。JS调用Native:
首先,通过拦截JavaScript text input panel
的prompt
事件来实现。
然后,解析调用方法字符串,找到对应的method,然后利用objc_msgSend
调用OC的方法。
设计将接口封装到自定义的JavaScriptInterface
中,支持多个JavaScriptInterface
类。内部维护一个字典javaScriptNamespaceInterfaces
,支持多个命名空间。Native调用JS:
参数和方法封装到DSCallInfo
(包含id、args、method字段),然后json字符串后,调用evaluateJavaScript:completionHandler:
执行js函数window._handleMessageFromNative
通知前端。内部默认初始化
InternalApis
对象,提供内部功能,例如是否有原生方法?提供调用js后,等待js的异步回调等。
1、JavaScript
核心原理
封装DSBridge,提供注册js的方法
register: function (name, fun, asyn)
;调用Native的方法call: function (method, args, cb)
等使用全局对象
window
,往window注入全局参数,如存储js的注册方法等。native调用的js方法动态注入
提供bridge.register(name, fun)
接口,使用key-value的方式将方法func和方法名method_name。
源码核心
- JS->Native核心:以下是源码缩减版本~
var bridge = {
// js调用native的方法入口
call: function (method, args, cb) {
arg = JSON.stringify(arg)
if(window._dsbridge){
ret= _dsbridge.call(method, arg)
}else if(window._dswk||navigator.userAgent.indexOf("_dsbridge")!=-1){
//使用时Native会注册_dswk参数
// 调用prompt函数,Native会拦截prompt事件,然后执行
ret = prompt("_dsbridge=" + method, arg);
}
return JSON.parse(ret||'{}').data
},
//Native调用的方法使用此方法注册
register: function (name, fun, asyn) {
//注册的方法会保存到_dsaf或_dsf中
var q = asyn ? window._dsaf : window._dsf
//object类型保存到_obs下,方法直接保存到_dsf(_dsaf)下
if (typeof fun == "object") {
q._obs[name] = fun;
} else {
q[name] = fun
}
}
};
- Native->JS核心:以下是源码缩减版本~
//立即执行函数
!function () {
//判断是否需要给window进行参数添加,如果没有添加会把ob内参数进行一次添加
if (window._dsf) return;
var ob = {
_dsf: {//存储同步方法
_obs: {}//存储同步方法相关object
},
_dsaf: {//存储异步方法
_obs: {}//存储异步方法相关object
},
dscb: 0,//避免方法同名每次加1
dsBridge: bridge,
_handleMessageFromNative: function (info) { //处理Native调用js方法,核心实现如下
// 通过info.method 获取方法实现
var f = this._dsf[info.method];
// 通过info.data 获取入参,数组形式
var arg = JSON.parse(info.data);
// 使用apply函数,调用函数
f.apply(ob, arg)
} //end
} // var ob end
}//func end