随着移动端盛行,不管是混合开发(Hybrid)应用,还是 React-Native 都离不开 JSBridge,当然也包括在国内举足轻重的微信小程序。
JSBridge 的作用
通过 JSBridge 可以实现 H5 和 原生之间的双向通信,主要是给 H5 提供调用 原生(Native)功能的接口,让混合开发中的 H5 可以方便地使用地址位置、摄像头甚至支付等原生功能。
JSBridge 的通信原理
主要有两种:注入 API 和 拦截 URL SCHEME。
注入 API
注入 API 方式是最常用的方式,主要原理是通过 WebView
提供的接口,向 JavaScript 的 Context(window)中注入对象或者方法,让 JavaScript 调用时,直接执行相应的 Native 代码逻辑,达到 JavaScript 调用 Native 的目的。
注入 API 时,H5 端的代码
1)初始化 WebViewJavascriptBridge
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| const u = navigator.userAgent;
const isAndroid = u.indexOf("Android") > -1 || u.indexOf("Adr") > -1;
const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
const iosFunction = (callback) => { if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement("iframe"); WVJBIframe.style.display = "none"; WVJBIframe.src = "demo://__BRIDGE_LOADED__"; document.documentElement.appendChild(WVJBIframe); setTimeout(function () { document.documentElement.removeChild(WVJBIframe); }, 0); };
const androidFunction = (callback) => { if (window.WebViewJavascriptBridge) { callback(window.WebViewJavascriptBridge); } else { document.addEventListener( "WebViewJavascriptBridgeReady", function () { callback(window.WebViewJavascriptBridge); }, false ); } };
window.setupWebViewJavascriptBridge = isAndroid ? androidFunction : iosFunction;
isAndroid && window.setupWebViewJavascriptBridge(function (bridge) { bridge.init(function (msg, responseCallback) { responseCallback("JS 返回给原生的消息内容"); }); });
|
2)注册与原生交互的事件函数
1 2 3 4 5 6 7 8
| window.setupWebViewJavascriptBridge((bridge) => { bridge.registerHandler("H5Function", (data, callback) => { callback && callback(); }); });
|
3)调用原生注册的事件函数
1 2 3 4 5 6
| window.setupWebViewJavascriptBridge((bridge) => { bridge.callHandler("changeData", data, (result) => { console.log(result); }); });
|
拦截 URL SCHEME
先解释一下 URL SCHEME:URL SCHEME 是一种类似于 url 的链接,是为了方便 app 直接互相调用设计的,形式和普通的 url 近似,主要区别是 protocol
和 host
一般是自定义的
例如打开微信扫码的 SCHEME:weixin://scanqrcode
protocol 是 weixin,host 则是 scanqrcode
拦截 URL SCHEME 的主要流程
Web 端通过某种方式(例如 iframe.src
)发送 URL Scheme 请求,之后 Native 拦截到请求,并根据 URL SCHEME(包括所带的参数)进行相关操作(类似JSONP
的方式)
URL SCHEME 的缺陷
1)使用 iframe.src
发送 URL SCHEME 会有 url 长度的隐患
2)创建请求,需要一定的耗时,比注入 API 的方式调用同样的功能,耗时会较长