vue项目中使用WebViewJavascriptBridge与Android和ios交互,以及遇到的坑

1,415 阅读1分钟

上代码

1.创建 src/utils/bridge.js文件,用于封装 WebViewJavascriptBridge

2.bridge.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) {
        // 客户端需要调用的js函数
        setupWebViewJavascriptBridge(function (bridge) {
            bridge.registerHandler(name, function (data, responseCallback) {
                callback(data, responseCallback)
            })
        })
    },
}

3.在main.js中引入该文件:

import bridge from './util/bridge' //引用WebViewJavascriptBridge
Vue.prototype.$bridge=bridge;

在需要调用客户端方法的组件中调用(事先需要与客户端同事约定好方法名)

let params={} //需要传给客户端的参数
this.$bridge.callhandler("事先与客户端同事约定好的方法名", params, (data) => {
     // alert(data) 返回的数据
    // 处理返回数据
});

当客户端需要调用js函数的时候 (在对应的组件中注册事先约定的函数即可)

this.$bridge.registerhandler(
        "事先与客户端同事约定好的方法名",
        (data, responseCallback) => {
         // alert(data)  返回的数据
        // responseCallback(params); 如果有需要传给客户端同事的数据写在 params 里面 
});
到这里写完了 ,检查了一遍代码觉得没毛病 开始测试 在ios上一切正常。然而在Android上调用
this.$bridge.callhandler 在vue中回调却接收不到返回值,Android的同事也拿不到this.$bridge.registerhandler中
提前约定注册好的方法名。疯狂Google之后新增了以下代码:
let u = navigator.userAgent;
function setupWebViewJavascriptBridge(callback) {
  if (!/(iPhone|iPad|iPod|iOS)/i.test(u)) {  //Android使用
      if (window.WebViewJavascriptBridge) {
        callback(window.WebViewJavascriptBridge);
      } else {
        document.addEventListener(
          "WebViewJavascriptBridgeReady",
          function() {
            callback(window.WebViewJavascriptBridge);
          },
          false
        );
      }
   }else{ //IOS使用
        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)
    }
}
//注册回调函数,安卓
setupWebViewJavascriptBridge((bridge) => {
   if (!/(iPhone|iPad|iPod|iOS)/i.test(u)) {
          //android 有init初始化方法,必须调用 不调用后续注册的事件将无效 而IOS却没有init方法 调用会报错 
        bridge.init((message, responseCallback) => {
         var data = { "Javascript Responds": "Wee!" };
         console.log(message);
         responseCallback(data);
        });
    }
});

export default {
    callhandler(name, data, callback) {
        // 调用客户端的方法 
        setupWebViewJavascriptBridge(function (bridge) {
            bridge.callHandler(name, data, callback)
        })
    },
    registerhandler(name, callback) {
        // 客户端需要调用的js函数
        setupWebViewJavascriptBridge(function (bridge) {
            bridge.registerHandler(name, function (data, responseCallback) {
                callback(data, responseCallback)
            })
        })
    },
}    

改完以后再次测试 ,Android和ios测试通过。