native端到js端:native能获取到window环境,执行JS。
js端到native端:native能截获H5页面跳转,故而JS端可以通过动态创建iframe来告诉native,我发请求了。(其实就是在window下维护了一个messageQueue数组,然后js创建个iframe,告诉native,我向你发请求了,但具体是什么请求,url里面是不会体现的,需要native去遍历messageQueue数组,毕竟native能取到window环境 )。
window.AppWebVeiw = function (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)
}, 1);
};
重点是:window.WebViewJavascriptBridge 所有的交互都是通过这个WebViewJavascriptBridge对象来完成的。
初始化的过程就是动态创建一个iframe,将iframe的src设置为https://__bridge_loaded__,然后插入到页面中。前面通信基础说过,natvie能够截获h5跳转,当Native捕获到当前URL,并且其值等于 https://__bridge_loaded__ (当前URL是约定成俗的) ,就会注入一段自执行的代码(app那边实现并且执行),挂载WebViewJavascriptBridge到window上;
if (window.WebViewJavascriptBridge) 保证初始化只执行一次,window.WVJBCallbacks 这个数组 用于 WebViewJavascriptBridge对象为初始化完成时保存回调函数。当我们通知APP端进行初始化,并且初始化完成之后 WebViewJavascriptBridge 会去遍历 WVJBCallbacks 里面的 回调函数,执行完毕后会 delete window.WVJBCallbacks
初始化完成之后我们就可以注册一些 和 app 交互的事件了
AppWebVeiw(function (b) {
b.registerHandler('callHDBridgeHandler', function (msg, call) {
});
b.callHandler('registerHDBridgeHandler', {
name: "isReady"
}, function (r) {
/* 询问APP是否准备完 的回调 */
if (JSON.parse(r).name == "readyIsFinsh") GetReady = true;
});
});
其中 b.registerHandler 可以看到有两个参数 第一个是和 app 约定好的固定值的参数 第二个是 接收的app的回调函数 回调函数的第一个参数是app 发送的信息,第二个是给app的反馈 b.callHandler 这个多用来直接给app 发送消息 第一个参数同样是 和 app 约定好的固定参数 第二个是给app 发送的消息 第三个是app接收到消息后给的反馈结果
最后举例一些实际的应用场景
场景1:当前页面是否是用户正在浏览的页面 AppWebVeiw(function (b){ b.registerHandler('callHDBridgeHandler', function (msg, call) { if(msg.type==='isActive'){ //用户正在浏览该页面 }else if(msg.type==='goBack'){ //用户点击了回退操作 } }); })
场景2:获取当前用户信息
AppWebVeiw(function (b){
b.callHandler('registerHDBridgeHandler', {name:"userInfo"},function (msg, call) {
if(msg.accountName){
//获取到用户基本信息
}
});
})