uniapp H5嵌套通讯方案-webview&iframe
- 背景
- webview方案
-
- 父级
-
- 手机app调试情况
- H5情况
- 子级(嵌套页面)
-
- 手机app调试情况
- 父节点是H5情况
- 完整代码:
-
- 父亲
- 孩子
- iframe 方案
-
- 手机调试情况(app-plus)
-
- 父亲(app)
- 孩子(H5)
- 父亲页面也是H5情况
-
- 父亲H5
- 子H5
- 总结
背景
在我们使用uniapp制作app的项目的时候往往会有很多的场景需要使用到嵌入H5页面,比如需要渲染地图,会大量操作dom节点,或者echarts,以及一些依赖不适配app,但是很多功能H5页面是无法独立完成的,比如获取定位,比如在线浏览word文档,或者打开外部程序等,这时候我们就需要使用H5与外部的app建立通讯以下我将提供两个通讯方案的具体方法
-
webview
-
iframe
webview方案
值得注意的是webview方案会导致占满整个屏幕,这样app内的上边距就会消失,整个会很不好看,比如你是苹果刘海屏幕,那你的app嵌入的页面就会在顶部有一部分被遮挡。所以我们需要创建dom后设置webview的上边距以及高度,利用uniapp的条件编译语句判断是否是app-plus情况
以下直接上代码:
父级
手机app调试情况
父级app内的代码
<template>
<view class="content">
<web-view ref="webViewDom" :id="webviewId" src="http://..." @message="handleMessage"></web-view>
</view>
</template>
<script>
// 我定义的通讯标识符字典,方便通讯的全局管理
import {
WEB_VIEW_EVENT } from '@/api/AppEvent';
export default {
data () {
return {
wv: null, // 计划创建的 webview
webviewId: 'web-view', // 记录webview的id
}
},
onLoad () {
let height = 0; //定义动态的高度变量
let statusbar = 0; // 动态状态栏高度
uni.getSystemInfo({
// 获取当前设备的具体信息
success: (sysinfo) => {
statusbar = sysinfo.statusBarHeight;
height = sysinfo.windowHeight;
}
});
// #ifdef APP-PLUS
let currentWebview = this.$scope.$getAppWebview(); //获取当前web-view
const that = this
setTimeout(function () {
that.wv = currentWebview.children()[0];
that.wv.setStyle({
//设置web-view距离顶部的距离以及自己的高度,单位为px
top: statusbar,
height: height - statusbar,
})
}, 500);
// #endif
// 如果想向webview发送事件就调用postMessage方法
},
methods: {
// webview向外部发送消息--app 接收到的消息
handleMessage (event) {
console.log('接收到的消息:' JSON.stringify(event.detail.data));
this.detailMessage(event) // 处理信息
},
/**
* 处理 webview 向客户端传递 事件
*/
detailMessage (dataRes) {
let data = JSON.parse(JSON.stringify(dataRes));
const deviceEnvIsH5 = getApp().globalData.deviceEnvIsH5;
// #ifndef H5
data = dataRes.detail.data[0];
try {
if (deviceEnvIsH5) {
data = dataRes;
}
} catch (e) {
console.log(e);
}
// #endif
switch (data.action) {
case WEB_VIEW_EVENT.WEBVIEW_SUCCESS:
console.log('webView加载成功', data);
break;
case WEB_VIEW_EVENT.MAP_SUCCESS:
console.log('地图MAP_SUCCESS', data);
...
break;
default:
break;
}
},
/**
* 向webview 发送消息
* @param action
* @param data
*/
postMessage (action, data) {
const deviceEnvIsH5 = getApp().globalData.deviceEnvIsH5;
// #ifdef H5
this.wv?.contentWindow?.postMessage({
action: action, data: data }, '*');
// #endif
// #ifndef H5
if (deviceEnvIsH5) {
// 宿主机在非h5中,但其实是嵌套的webview 还是走传统 webview 通信
this.wv?.contentWindow.postMessage({
action: action, data: data }, '*');
} else {
switch (action) {
case WEB_VIEW_EVENT.SEND_LOCATION: // 发送坐标
const str = JSON.stringify({
action: action, data: data }