需求: 在原生App里打开webview, 嵌入H5. 在H5中点击某个元素, 触发与native app交互, 又跳回到app中. 同理, 在app中完成某项操作后, 获得某个参数, 根据这个状态刷新页面.
框架: Vue. JavaScript原生的写法已经调通了, 并且与native端的已经联调通过. 所以这里是把它们迁移到Vue框架的写法.
这里要区分iOS系统和Android系统.
iOSϵͳ
- 在这里与iOS开发的同事协商后, 决定使用 WebViewJavascriptBridge来开发. 前端不需要放入任何js插件. 只需要准备一下这段内容.
bridge.js
function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge) } if (window.WVJBCallbacks) { returnwindow.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 { callhandlerIOS(name, data, callback) { setupWebViewJavascriptBridge(function (bridge) { bridge.callHandler(name, data, callback) }) }, registerhandlerIOS(name, callback) { setupWebViewJavascriptBridge(function (bridge) { bridge.registerHandler(name, function (data, responseCallback) { callback(data, responseCallback) }) }) } }
- 在main.js里注入
import Bridge from "./js/bridge.js"; Vue.prototype.$bridge = Bridge //在这里注入后, 页面里所有需要用到调用native的地方, 都可以直接调用this.$bridge.xxx new Vue({ el: "#app", router, store, // Bridge, components: { App }, template: "<App/>", })
- 在要使用的
.vue
文件里使用
这里举一个例子.
在callNative
方法里使用this.$bridge.callhandler(‘ObjC Echo‘, params, function(response){//todo})
其中ObjC Echo
是和客户端约定好的方法. 即在客户端注册好的方法, 写上这个方法名, 在使用的时候客户端就能接收到, 从而拿到params里的参数, 而后面跟的function(response){}
就是处理response里的数据. 进行一些操作.
this.$bridge.callhandlerIOS( "HY_H5_CALL_NATIVE", { action: "pick me" }, data => { // 处理返回数据 } )
使用this.$bridge.registerhandler(‘JS Echo‘, (data, responseCallback)=>{//todo}
JS Echo
即是和客户端约定好的方法名, 在客户端使用这个方法名时, 会自动调起H5执行某些操作. 客户端传来的信息放在data
里, responseCallback
即执行回调.
this.$bridge.registerhandlerIOS("JS Echo", (data, responseCallback) => { alert("JS Echo called with:", data); // this.responseCallback(data) });
Androidϵͳ
由于Android系统同样也使用webviewJavaScriptBridge, 所以我自然而然想到了是否也能像iOS一样export出两个处理的handler.
- 在bridge.js中添加声明代码
//Android 交互声明 function connectWebViewJavascriptBridgeANDROID(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge); } else { document.addEventListener( "WebViewJavascriptBridgeReady", function () { callback(WebViewJavascriptBridge); }, false ); } }
- 在bridge.js的export中添加导出
这里我在handler后面添加了Android作为和iOS的handler做区分.
callhandlerAndroid(name, data, callback){ //Android方法 connectWebViewJavascriptBridgeANDROID(function(bridge){ bridge.callHandler(name, data, callback) }) }, registerhandlerAndroid(name, callback){ //Android方法 connectWebViewJavascriptBridgeANDROID(function(bridge){ bridge.init(function(message, responseCallback) { if (responseCallback) { // responseCallback(data); } }); bridge.registerHandler(name, function(data, responseCallback){ callback(data, responseCallback) }) }) }
- 在
.vue
文件中使用. 使用方法同iOS
this.$bridge.callhandlerAndroid( ‘action‘, {message: ‘111‘}, function(response){} )
this.$bridge.registerhandlerAndroid( "registerAction", (message, responseCallback) => { alert("JS Echo called with:" + message); // this.responseCallback(data) } );
至此, js和Android, iOS端就算调通了.
感觉Android这一块还有很多可以优化的地方, 但是我的js还掌握的不是很牢靠...所以就先这样吧. 等以后我又新的感悟了, 再来更新.
附上所有代码
- bridge.js代码
//iOS 交互声明 function connectWebViewJavascriptBridgeIOS(callback) { if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge) } if (window.WVJBCallbacks) { returnwindow.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) } //Android 交互声明 function connectWebViewJavascriptBridgeANDROID(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge); } else { document.addEventListener( "WebViewJavascriptBridgeReady", function () { callback(WebViewJavascriptBridge); }, false ); } } export default { callhandlerIOS(name, data, callback) { //iOS的方法 connectWebViewJavascriptBridgeIOS(function (bridge) { bridge.callHandler(name, data, callback) }) }, registerhandlerIOS(name, callback) { //iOS的方法 connectWebViewJavascriptBridgeIOS(function (bridge) { bridge.registerHandler(name, function (data, responseCallback) { callback(data, responseCallback) }) }) }, callhandlerAndroid(name, data, callback){ //Android方法 connectWebViewJavascriptBridgeANDROID(function(bridge){ bridge.callHandler(name, data, callback) }) }, registerhandlerAndroid(name, callback){ //Android方法 connectWebViewJavascriptBridgeANDROID(function(bridge){ bridge.init(function(message, responseCallback) { if (responseCallback) { // responseCallback(data); } }); bridge.registerHandler(name, function(data, responseCallback){ callback(data, responseCallback) }) }) } }
- main.js代码
import Bridge from "./js/bridge.js"; Vue.prototype.$bridge = Bridge /* eslint-disable no-new */ new Vue({ el: "#app", router, store, components: { App }, template: "<App/>", });
.vue
文件
<template> <div> <h1>hi, this is a test</h1> <h2 v-if="isShow">234</h2> <button @click="callNative">点击点击</button> <h3>234</h3> </div> </template> <script> export default { data() { return { isShow: false }; }, created() { this.$bridge.registerhandlerIOS("JS Echo", (data, responseCallback) => { alert("JS Echo called with:", data); // this.responseCallback(data) }); this.$bridge.registerhandlerAndroid( "registerAction", (message, responseCallback) => { alert("JS Echo called with:" + message); // this.responseCallback(data) } ); }, methods: { callNative() { this.isShow = !this.isShow; if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { this.$bridge.callhandlerIOS( "HY_H5_CALL_NATIVE", { action: "pick me" }, data => { // 处理返回数据 } ) }else if (/(Android)/i.test(navigator.userAgent)){ this.$bridge.callhandlerAndroid( ‘action‘, {message: ‘111‘}, function(response){} ) } }, } }; </script> <style> button { margin: 30px auto; display: block; padding: 10px; border: 1px solid #ccc; background-color:dodgerblue } </style>
原文:https://www.cnblogs.com/darthbadwolf/p/9336651.html