main.js
new vue({
el: "#app",
router,
components: {
App
},
template: "<App/>",
created() {
(function() {
if (window.WebViewJavascriptBridge) {
return;
}
var messagingIframe;
var sendMessageQueue = [];
var receiveMessageQueue = [];
var messageHandlers = {};
var CUSTOM_PROTOCOL_SCHEME = 'yy';
var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';
var responseCallbacks = {};
var uniqueId = 1;
function _createQueueReadyIframe(doc) {
messagingIframe = doc.createElement('iframe');
messagingIframe.style.display = 'none';
doc.documentElement.appendChild(messagingIframe);
}
//set default messageHandler
function init(messageHandler) {
if (WebViewJavascriptBridge._messageHandler) {
throw new Error('WebViewJavascriptBridge.init called twice');
}
WebViewJavascriptBridge._messageHandler = messageHandler;
var receivedMessages = receiveMessageQueue;
receiveMessageQueue = null;
for (var i = 0; i < receivedMessages.length; i++) {
_dispatchMessageFromNative(receivedMessages[i]);
}
}
function send(data, responseCallback) {
_doSend({
data: data
}, responseCallback);
}
function registerHandler(handlerName, handler) {
messageHandlers[handlerName] = handler;
}
function callHandler(handlerName, data, responseCallback) {
_doSend({
handlerName: handlerName,
data: data
}, responseCallback);
}
//sendMessage add message, 触发native处理 sendMessage
function _doSend(message, responseCallback) {
if (responseCallback) {
var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
responseCallbacks[callbackId] = responseCallback;
message.callbackId = callbackId;
}
sendMessageQueue.push(message);
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
}
// 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
function _fetchQueue() {
var messageQueueString = JSON.stringify(sendMessageQueue);
sendMessageQueue = [];
//android can't read directly the return data, so we can reload iframe src to communicate with java
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
}
//提供给native使用,
function _dispatchMessageFromNative(messageJSON) {
setTimeout(function() {
var message = JSON.parse(messageJSON);
var responseCallback;
//java call finished, now need to call js callback function
if (message.responseId) {
responseCallback = responseCallbacks[message.responseId];
if (!responseCallback) {
return;
}
responseCallback(message.responseData);
delete responseCallbacks[message.responseId];
} else {
//直接发送
if (message.callbackId) {
var callbackResponseId = message.callbackId;
responseCallback = function(responseData) {
_doSend({
responseId: callbackResponseId,
responseData: responseData
});
};
}
var handler = WebViewJavascriptBridge._messageHandler;
if (message.handlerName) {
handler = messageHandlers[message.handlerName];
}
//查找指定handler
try {
handler(message.data, responseCallback);
} catch (exception) {
if (typeof console != 'undefined') {
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);
}
}
}
});
}
//提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
function _handleMessageFromNative(messageJSON) {
// console.log(messageJSON);
if (receiveMessageQueue && receiveMessageQueue.length > 0) {
receiveMessageQueue.push(messageJSON);
} else {
_dispatchMessageFromNative(messageJSON);
}
}
var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
init: init,
send: send,
registerHandler: registerHandler,
callHandler: callHandler,
_fetchQueue: _fetchQueue,
_handleMessageFromNative: _handleMessageFromNative
};
var doc = document;
_createQueueReadyIframe(doc);
var readyEvent = doc.createEvent('Events');
readyEvent.initEvent('WebViewJavascriptBridgeReady');
readyEvent.bridge = WebViewJavascriptBridge;
doc.dispatchEvent(readyEvent);
})();
//用于和APP的原生方法交互(在H5的项目中主要调用isapp的方法判定是否在APP中来判断是否显示导航栏)
let isAndroid = navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Adr') > -1;
let isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
//Android
function androidWebView(data) {
let result = null;
let name = data.name;
let callback = () => { };
if (('data' in data)) {
if(data.data instanceof Array){
// console.log(data.data)
result = window.control[name](...data.data);
} else {
let _data = 'type' in data ? data.data :data.data ? JSON.stringify(data.data) : '';
// console.log(_data)
result = window.control[name](_data);
// console.log(result)
}
} else {
result = window.control[name]();
}
if(('callback' in data)){
callback = data.callback;
}
callback(result);
}
// ios
function iosWebView(callback,data) {
if (window.WKWebViewJavascriptBridge) {return callback(window.WKWebViewJavascriptBridge); }
if (window.WKWVJBCallbacks) {return window.WKWVJBCallbacks.push(callback); }
window.WKWVJBCallbacks = [callback];
window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null)
}
function callH(data) {
if (isiOS) {
iosWebView(function (bridge) {
let _data = "";
if('data' in data && data.data instanceof Array){
if(data.data.length > 0){
_data = "";
data.data.map(item=>{
_data += item + ','
})
}
data.data = _data;
}
if(!('callback' in data)){
data.callback = ()=>{};
}
bridge.callHandler(data.name, {'data':data.data}, data.callback)
})
} else {
androidWebView(data)
}
};
// APP调js方法 (参数分别为:js提供的方法名 回调)
function registerH(name, callback) {
if (isiOS) {
iosWebView(function (bridge) {
bridge.registerHandler(name, function (data, responseCallback) {
callback(data, responseCallback({'Javascript Says':'Right back atcha!'}))
})
})
} else {
window[name] = callback;
}
}
window.callH = callH;
window.registerH = registerH;
}
})
使用方式:
调用客户端的方法:
// 例如将客户端解密后的数据绑定到自己定义的属性上
callH({
name: '客户端解密方法',
data: resp.data.data, //传给客户端的数据
callback: (res) => { //res为解密方法解密后返回的数据
resp.data.real = JSON.parse(res);
}
})
客户端调用h5的方法(比如跳转某个页面),必须在一进入页面注册方法
mounted(){
registerH("协商好的方法名(H5自己定义)", this.方法名字)
},
methods: {
方法名() {
this.$router.push("/路由");
},
}