概述
由于混合应用的开发具有灵活性、可移植性和易维护性等优点,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>