项目背景:现有H5项目,要快速完成一个app开发,由于周期紧张只能先用H5套壳完成一版app
一 、什么是webViewjavascripBridge?
WebViewJavascriptBridge是移动UIView和Html交互通信的桥梁,用白话来说就是实现java(ios为oc)和js的互相调用的桥梁。替代了WebView的自带的JavascriptInterface的接口,使得我们的开发更加灵活和安全。
二、如何在vue中使用?
这里使用的是vue-bridge-webview(也就是对WebViewJavascriptBridge进行了二次封装 git地址),类似的封装还有vue-webview-js-bridge(这位大神封装的太过于高端,测试使用的时候交互死活无效,有知道怎么用的欢迎指点 git地址),好了进入正题,这里与原生进行交互以调取原生摄像头进行扫一扫为例。
1.先进行安装
npm install vue-bridge-webview --save
2.在main.js中引入使用
常规做法:
import Vue from 'vue'
import bridge from 'vue-bridge-webview'
Vue.use(bridge)
我的处理(至于为什么这么做,后面会解释,先标个星★ ):
import bridge from '../static/vue-bridge-webview'
Vue.use(bridge)
3.在需要调用安卓/ios原生方法的组件中直接使用即可
点击事件中调客户端方法,完成扫一扫,这就是 js—>原生
methods: {
//扫码
handel_scan() {
this.$bridge.callHandler("setCamera", data => { //这里的setCamera是客户端同同事定义的方法名,因为调取摄像头,没有传参
console.info('扫码');
});
//调取原生方法api*JS invoke Android/IOS
$bridge.callHandler: function(name,params,callback) // callback name, request params, callback function
example: get userInfo
[this|Vue|window].$bridge.callHandler('getUserInfo',{},function(data){
//要做的事情
})
},
}
调取客户端方法,进行扫码,如图:
扫码之后的结果需要从客户端的方法中传递给H5这边去处理结果,这就需要客户端那边调js,这就是 原生—>js
既然需要客户端调js方法,前端就需要注册一个js方法,供客户端同事调取
注册方法也很简单
created() {
let _this = this;
this.$bridge.registerHandler("getScanRes", (data, responseCallback) => { //getScanRes前端定义的方法名
// _this.$router.push({ path: "/record", query: { code: data } });
console.info("扫码结果",data)
});
//注册方法api*Android/IOS invoke JS
$bridge.registerHandler : function(name, registerCallback) // callback name, callback function
example: refersh page view
[this|Vue|window].$bridge.registerHandler("refreshPage",function(){
//要做的事情
})
},
传递过来的扫码结果,如图:
至此就完成了一个双向的交互。
遇到问题(也就是上面标星的为什么那么写):
在js中注册了方法,在ios和android两个平台使用,结果是ios调用ok, android死活调用不了,最重要的是 js去调用android的方法却可以, 并且用webviewjavascriptbridge的github库里的示例example.html来测试两个平台都ok。
这就有点难受了…为啥ios可以调用js的方法android却不可以, 初始化应该是没问题的, 不然js调用android的方法也会失败。
解决办法:
查找一些资料,最终得知在安卓上面需要init,于是我把node_modules里面的vue-bridge-webview.js文件给提取了出来,放到了static里面,更改了一下里面的代码:
更改前:
更改后:
有的人会产生疑问是不是二次封装造成的?如果直接使用WebViewJavascriptBridge呢?答案:不是二次封装引起的。
直接引入WebViewJavascriptBridge.js进行了测试:
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(window.WebViewJavascriptBridge)
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback)
}
window.WVJBCallbacks = [callback]
let WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none'
WVJBIframe.src = 'https://__bridge_loaded__'
document.documentElement.appendChild(WVJBIframe);
setTimeout(() => {
document.documentElement.removeChild(WVJBIframe)
}, 0)
}
export default {
callhandler(name, data, callback) {
setupWebViewJavascriptBridge(function (bridge) {
bridge.callHandler(name, data, callback)
})
},
registerhandler(name, callback) {
setupWebViewJavascriptBridge(function (bridge) {
bridge.registerHandler(name, function (data, responseCallback) {
callback(data, responseCallback)
})
})
}
}
挂载在原型
import Bridge from './config/bridge.js'
Vue.prototype.$bridge = Bridge
使用的时候惊奇的发现,是一样的效果,说白了vue-bridge-webview的二次封装并没有更改什么只是对不同端做了处理。
至于WebViewJavascriptBridge在安卓调用js的时候为什么要init,我也不知道,总之问题解决了,不对地方欢迎指正。