qappleh / Interview

我是追梦赤子心,公众号「深圳湾码农」的作者,某上市集团公司高级前端开发,深耕前端领域多年,每天攻破一道题,带你从0到1系统构建web全栈完整的知识体系!
https://github.com/qappleh/Interview
1.15k stars 97 forks source link

第304题(2020-09-16):H5页面和原生APP是怎么通信的? #307

Open qappleh opened 4 years ago

qappleh commented 4 years ago

H5与原生app交互,需要WebViewJavascriptBridge,废话不多直接上代码,下面是项目中的封装bridge.js的全部代码(示例代码为vue)

//iOS 交互声明
function connectWebViewJavascriptBridgeIOS(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 = 'wvjbscheme://__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 {
  //H5调用Native
  callhandler(name, data, callback) {
    //iOS的方法
    if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
      connectWebViewJavascriptBridgeIOS(function (bridge) {
        bridge.callHandler(name, data, callback)
      })
    }
    //Android方法
    if (/(Android)/i.test(navigator.userAgent)) {
      connectWebViewJavascriptBridgeANDROID(function (bridge) {
        bridge.callHandler(name, data, callback)
      })
    }
  },
  //Native调用H5
  registerhandler(name, callback) {
    //iOS的方法
    if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
      connectWebViewJavascriptBridgeIOS(function (bridge) {
        bridge.registerHandler(name, function (data, responseCallback) {
          callback(data, responseCallback)
        })
      })
    }
    //Android方法
    if (/(Android)/i.test(navigator.userAgent)) {
      connectWebViewJavascriptBridgeANDROID(function (bridge) {
        bridge.init(function (message, responseCallback) {
          if (responseCallback) {
            // responseCallback(data);
          }
        });
        bridge.registerHandler(name, function (data, responseCallback) {
          callback(data, responseCallback)
        })
      })
    }

  },

}

然后挂载到vue的原型方法上,在main.js中进行如下配置

import Bridge from "@/config/bridge.js" //此路径根据实际bridge.js路径填写
Vue.prototype.$bridge = Bridge

完事儿,下面看一下在实际使用中的用法

methods: {
    // h5调用原生方法,testWebViewBridge为原生app定义的方法名。action为h5传递给原生app的参数,可以为多个。data为原生app传递给h5参数
    goNative() {
      const vm = this;
      this.$bridge.callhandler(
        "testWebViewBridge",
        { action: "pick me" },
        data => {
          vm.ddd = data;

          // 处理返回数据
        }
      );
    },
    // h5注册方法,供app调用
    iosToH5(){

    },
  },

  mounted() {
    // 原生app调用h5方法,iosToH5是methods中定义的方法名。
    const vm = this;
    this.$bridge.registerhandler("iosToH5", (data, responseCallback) => {
      // data是原生app传递给h5的参数
      vm.native_data = data;
    });
  }