uniapp H5嵌套通讯方案-webview&iframe

本文介绍了在uniapp中使用webview和iframe实现H5页面与app、H5之间的通信方案。针对webview,详细讲解了父级和子级的处理方式,包括在app和H5环境下的通信实现;而对于iframe方案,讨论了其在不同环境下的优缺点及应用。

背景

在我们使用uniapp制作app的项目的时候往往会有很多的场景需要使用到嵌入H5页面,比如需要渲染地图,会大量操作dom节点,或者echarts,以及一些依赖不适配app,但是很多功能H5页面是无法独立完成的,比如获取定位,比如在线浏览word文档,或者打开外部程序等,这时候我们就需要使用H5与外部的app建立通讯以下我将提供两个通讯方案的具体方法

  1. webview

  2. 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 
### 在 H5 页面中嵌套 UniApp 并正确使用微信小程序 API #### 1. **H5 页面嵌套 UniApp** 要将 UniApp 嵌入到 H5 页面中,主要依赖于 WebView 组件。具体来说,可以在 H5 中通过 iframe 或者直接加载 UniApp 构建的 Web 版本地址。 以下是实现的关键步骤: - **构建 UniAppH5 版本** 使用 UniApp 提供的命令行工具打包生成 H5 资源文件夹,并将其部署到服务器上[^2]。 - **在 H5 页面中嵌入 UniApp** 将 UniApp 的入口 HTML 地址作为 iframe 的 `src` 属性值传入。 ```html <iframe id="uniapp-frame" src="https://your-server/uniapp/index.html" style="width:100%; height:100vh; border:none;"></iframe> ``` 这样就可以实现在 H5 页面中嵌套显示 UniApp 应用了[^3]。 --- #### 2. **在 H5 中调用微信小程序 API** 当需要在 H5 环境下调用微信小程序特有的 API(如 `wx.downloadFile` 和 `wx.openDocument`)时,可以通过以下两种方式进行处理: ##### (1)检测运行环境并切换逻辑 由于这些 API 是专门为微信小程序设计的,在普通的 H5 环境下无法直接使用。因此需要先判断当前是否处于微信环境中再决定采用何种策略。 ```javascript // 检测是否为微信浏览器 var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf('micromessenger') !== -1) { // 微信环境下跳转至小程序页面进行操作 wx.miniProgram.navigateTo({ url: '/pages/download-page/download-page?url=' + encodeURIComponent(downloadUrl), }); } else { // 非微信环境下执行常规 H5 下载逻辑 handleH5Download(downloadUrl); } function handleH5Download(url) { var link = document.createElement('a'); link.href = url; link.target = '_blank'; link.rel = 'noopener noreferrer'; link.click(); } ``` 此部分代码实现了根据不同环境分别调用适合的方法来完成相同的目标功能[^4]。 --- ##### (2)通过 web-view 实现跨域通信 如果希望在已有的小程序项目里嵌入外部网页并通过它访问本地资源或者能力,则需要用到 `web-view` 标签配合消息通道机制。 ###### A. **设置 web-view 容器** 在小程序端创建一个专门用来承载目标网站的新页面,并在其 wxml 文件内加入如下结构: ```xml <web-view src="{{webViewSrc}}"></web-view> ``` 同时绑定数据变量以便动态调整加载的内容路径。 ###### B. **建立双方通讯桥梁** 为了让两者之间能够相互传递必要的参数信息,必须依靠 WeChat Mini Program 提供的标准接口——`postMessage` 和事件监听器组合达成目的。 - **从小程序向 H5 发送指令** ```javascript const webViewContext = wx.createWebViewContext('webview-id'); webViewContext.postMessage({ action: 'download', payload: { fileUrl } }); ``` - **从 H5 接收来自小程序的消息** ```javascript window.addEventListener('message', function(event){ let data = event.data; switch(data.action){ case 'download': performDownloadOperation(data.payload.fileUrl); break; default: console.warn(`Unknown command received: ${data.action}`); } }); function performDownloadOperation(url){ fetch(url,{ method:'GET', responseType:'arraybuffer' }).then(response=>response.blob()).then(blob=>{ saveAs(blob,'filename.ext'); }).catch(err=>console.error(err)); } ``` 以上片段展示了如何利用 postMessage 技术让两个独立的应用组件间形成紧密协作关系[^3]。 --- #### 3. **实际案例分析:结合 `wx.downloadFile` 和 `wx.openDocument`** 假设我们需要在一个混合场景应用中支持 PDF 文件的在线浏览与离线存储需求,那么完整的解决方案可能涉及以下几个方面的工作: - 如果是在纯 H5 上,则优先考虑基于 Blob 对象的方式生成临时链接让用户点击触发下载; - 若发现用户正在使用微信客户端浏览我们的站点,则进一步区分其是否有权进入关联的小程序空间继续下一步骤; - 进入小程序后按照既定流程依次调用 `wx.downloadFile` 获取远程资料副本存放到沙盒区域后再交给 `wx.openDocument` 处理展示给终端使用者看。 综合运用前面提到的技术要点可以很好地满足此类复杂业务诉求。 --- ###
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Freedom风间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值