Hybrid App :uniapp+h5混开

751 阅读2分钟

概述

由于混合应用的开发具有灵活性、可移植性和易维护性等优点,Hybrid App(混合应用)的开发变得越来越流行,甚至成为一种烂大街的存在,大到全民超级 App 微信、支付宝,小到随便的一个独立电商 App 都是 Hybrid App 的“忠实粉丝”。Hybrid App 作为一种既能够在原生应用程序环境中运行,也能够在 Web 浏览器中运行的应用程序。它主要使用 Web 技术进行开发,如 HTML、CSS 和 JavaScript,并使用一个中间层将其封装在原生应用程序中。 这篇文章我们直接倒反天罡直接使用uniapp+h5使用完成混开。uniapp提供原生功能,直接摒弃原生开发,领先世界无数个大版本!!!!!!

Uniapp + H5

uniapp 是一种基于 JavaScript 的混合应用开发框架,在国内跨端开发中普受欢迎。它允许开发人员使用 JavaScript、TypeScript 或 vue 来构建原生应用程序,并支持 Android、iOS 和 Web、小程序等。 h5我们直接使用react构建!!!

Jsbrid SDK的设计与实现

子应用

引入 js.cdn.aliyun.dcloud.net.cn/dev/uni-app… 对webview通讯封装

let callBackMap = {} // 全局回调集合: 一定时间内不会堆积太多函数,暂不做清除处理
// 绑定回调
function bindCallback(type, timestamp) {
    uni.getEnv(function (data) {//eslint-disable-line
        if (data.plus) {
            window[type] = val => {
                callBackMap[timestamp] && callBackMap[timestamp](val)
                window[type] = null
            }
        } else if (data.h5) {
            //  h5环境 不能使用eval  不允许跨域 所以只能使用message事件  如果说是同域 下 都可使用方案
            window.onmessage = callback
        }
    })
}
// 回调处理
function callback(val) {
    try {
        let data = JSON.parse(val.data)
        if (callBackMap[data.timestamp] || allBackMap[data.timestamp] === null) {
            callBackMap[data.timestamp] && callBackMap[data.timestamp](data)
            window.onmessage = null
            delete callBackMap[data.timestamp]
        }
    } catch (e) {
        // 默认为非法攻击
    }
}
// 调用方法
function utilsMessage(options) {
    let timestamp = Date.now()
    callBackMap[timestamp] = options.callBack || null
    bindCallback(options.method, timestamp)
    uni.postMessage({
        data: {
            method: options.method,
            timestamp: timestamp,
            params: {
                ...options.params
            }
        }
    })
}

这里封装时 对环境进行了区分 针对h5和app使用了不同的方式触发callBack 主要是因为在h5环境中eavl方法不支持跨域 所以在app使用了eavljs方式实现 ,h5使用onmessage实现。

//index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>h5页面</title>
</head>
<body>
   <button>点我调取原生共功能</button>
   <script src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
    <script type="module">
        import utilsMessage from './utils.js'
        function click() {
            utilsMessage({
                method: 'test',
                callBack: (res) => {
                    alert(res.result)
                }
            })
        }
        document.querySelector('button').addEventListener('click', click)
    </script>
</body>
</html>

父应用

封装webview 提供sdk给h5使用

<template>
  <view>
    <web-view :isfullscreen="false"  ref="webview" class="webviewclass" id="webviewiframe"
      src="http://127.0.0.1:5500/index.html"
      @message="handleMessage"></web-view>
  </view>
</template>

<script lang="ts">
import { defineComponent,getCurrentInstance, reactive, ref, onBeforeUnmount,onMounted, nextTick,} from "vue";
export default defineComponent({
  setup(props, { attrs, slots, emit, expose }) {
    function handleMessage(event: any) {
    let data
    //#ifdef APP-PLUS
     data = event.detail.data[0];
    // #endif
    // #ifdef H5
    data = event.data.data.arg;
    // #endif
     if (data) {
      if(data.method=='test'){
          //处理数据
          evalJs(data.method,JSON.stringify({
            timestamp: data.timestamp||data.params.timestamp,
            success: true,
            result: "hhhhhh",
          }),)
       } 
      }
    }
    // #ifdef H5
    const webview = ref<any>(null);
    window.addEventListener("message", handleMessage);
    onBeforeUnmount(() => {
      window.removeEventListener("message", handleMessage);
    });
    // #endif
    evalJS(method: string, data: any) {
      // #ifdef APP-PLUS
        let wv = this.currentWebview.children()[0];
        wv.evalJS(`${method}(${JSON.stringify(data)})`);
      // #endif
      // #ifdef H5
      var iframe: any = document.getElementById("webviewiframe");
      iframe.contentWindow.postMessage(JSON.stringify(data.arg), "*");
      // #endif
    },
});

</script>

实现效果

图片.png