一个做iOS的朋友找到我说,想要做到iOS原生和的webview的H5交互,我向他推荐了WebViewJavaScriptBridge。他说H5相关的他不会,让我给他写个例子。我就简单写了一个demo,记录一下。
原理什么的就不说了,先看怎么用,下面就直接上代码吧:
iOS 原生处理
// 引入
pod "WebViewJavascriptBridge"
//webview 注入 bridge
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
[self.bridge setWebViewDelegate:self];
iOS 使用
// app监听js调用事件
[self.bridge registerHandler:@"jsCallAppFunc" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"jsCallAppFunc:, %@", data);
}];
//app 直接调用js方法
[self.bridge callHandler:@"appCallJsFunc" data:@{@"name": @"
js,我来自app"} responseCallback:^(id responseData) {
NSLog(@"这是 js 又回传回来的数据:: %@", responseData);
}];
他主要是不懂js,下面是h5 的处理部分,直接上完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js bridge test</title>
</head>
<body>
//测试用
<button onclick="btnClick()">点击调用app方法</button>
<div>app 传给html的参数 显示在下面</div>
<div id='cont'></div>
<script>
// 固定代码
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 = 'wvjbscheme://__BRIDGE_LOADED__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function () { document.documentElement.removeChild(WVJBIframe) }, 0)
}
// 监听app 调用js 的事件
setupWebViewJavascriptBridge(function (bridge) {
bridge.registerHandler('appCallJsFunc', function (data, responseCallback) {
// app的参数展示出来
document.getElementById('cont').innerHTML = 'app传来参数:' + JSON.stringify(data)
//下面这一段是回调给app的参数,无需求可以不调用
// responseCallback({ 'subject': 'app,参数收好' })
})
})
// js 主动去触发app的方法
function btnClick() {
setupWebViewJavascriptBridge(function (bridge) {
bridge.callHandler('jsCallAppFunc', { 'title': '这是js传给app的参数' }, function (response) {
console.log('app 回调回来的参数')
})
})
}
</script>
</body>
</html>
测试了一下,双方通讯没有问题,可以直接使用。
后来他又说,以后用的地方可能会很多,能不能简单封装一下,想着闲来无事,简单封装一下吧。
// 独立出一个单独的js,方便各处引用:app.webview.bridge.js
; (() => {
/**
* app发送过来的 事件列表
*/
const NativeEvent = [
'appCallJsFunc'
]
/**
* 向app发送的 事件列表
*/
const JSCallNativeEvent = [
'jsCallAppFunc'
]
/**
* 固定的代码
* */
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 = 'wvjbscheme://__BRIDGE_LOADED__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function () { document.documentElement.removeChild(WVJBIframe) }, 0)
}
/**
* 定义插件
* */
var _app_webview_ridge = {}
/**
* 注册app事件
* */
NativeEvent.map(event => {
_app_webview_ridge[event] = callback => {
setupWebViewJavascriptBridge(bridge => {
bridge.registerHandler(event, (data, responseCallback) => {
callback(data, responseCallback)
})
})
}
})
/**
* 注册js事件
* */
JSCallNativeEvent.map(event => {
_app_webview_ridge[event] = (data, callback)=> {
setupWebViewJavascriptBridge((bridge) => {
bridge.callHandler(event, data, response => {
callback(response)
})
})
}
})
/**
* 定义插件的名称
*/
this.appWebviewBridge = _app_webview_ridge;
})()
h5 使用就简单了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js bridge test</title>
<script src="./app.webview.bridge.js"></script>
</head>
<body>
//测试用
<button onclick="btnClick()">点击调用app方法</button>
<div>app 传给html的参数 显示在下面</div>
<div id='cont'></div>
<script>
//可以查看整个对象有哪些方法可以调用
console.log(appWebviewBridge)
/**
* 1,监听app的事件:appCallJsFunc,
* 2,接受app的参数:data(app不传参数进来,data为空)
* 3,处理完参数后,可以继续回传参数给app:responseCallback (非必要,可以不调用)
* */
appWebviewBridge.appCallJsFunc((data,responseCallback)=>{
console.log('这是从app拿到的参数:' + JSON.stringify(data))
document.getElementById('cont').innerHTML = 'app传来参数:' + JSON.stringify(data)
// responseCallback({'title':'这是要给app的参数'})
})
/**
* 1,js 主动触发app的方法
* 2,{'name':"app,这是我给你的参数"} 是传给app的参数,(app不需要参数,可以为空)
* 3,(res)=>{} app接到参数后又传回来的参数(可以不写)
*/
function btnClick(){
appWebviewBridge.jsCallAppFunc({'name':"app,这是我给你的参数"},(res)=>{
console.log('app又给我参数了:' + JSON.stringify(res))
})
}
</script>
</body>
</html>
因为我没有专门再起个iOS程序了,所以封装完直接丢给了他,后台他说可以直接使用,我也就没仔细测试了,有问题可以直接提给我,我再修改。