uniapp的webview和H5相互通讯

本文详细阐述了在uniapp项目中,如何通过webview实现与嵌入的H5页面的双向通讯,特别关注于高德地图功能的集成,包括定位、地图事件监听和数据交换,适合寻求uniapp与H5交互解决方案的开发者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

webview和H5页面双方通讯方式

首先,表示对uniapp官网文档的亲切问候,然后,以下代码是测试调试中通过的,我未正常打包app去测试。

友情提示:1、app跟H5如何通讯,代码备注已经写了,我自己测试是没问题的,app还没打包apk测试,不清楚打包后的,2、我的需求是高德地图方面的功能,uniapp官网提供功能太少了,所以嵌套H5页面,需要来回交互,

一整天就为了搞个通讯,血泪史,uniapp官网文档只介绍了H5向app通讯,坑逼,帮上小伙们的话,点个赞吧~

1、uniapp项目方面:代码全贴,webview的url最好加上时间戳

<template>
	<view>
		<web-view :src="url" @message="handleMessage"></web-view>
	</view>
</template>

<script>
	import { mapMenuShow } from '../../utils/MenuShow.js';
	export default {
		data() {
			return {
				longitude:'',//经度
				latitude:'',//纬度
				url:null,
				mapCenterPosition:[],//地图中心点
				linePosition:[],//测距的线路列表
				areaPosition:[],//绘画的多边形列表
				wv: null, // 定义(app)webview对象节点
			}
		},
		onLoad() {
		//开启高德定位功能,自己去源码视图配置定位和key
		   uni.getLocation({
		   	geocode:true,
		   	type: 'gcj02',
		   	success:(res)=>{
		   		console.log(res)
				this.longitude = res.longitude
				this.latitude = res.latitude
				this.url = `http://192.168.253.185:8000/index?longitude=${this.longitude}&latitude=${this.latitude}&id=1&token=token&timestamp=${new Date().getTime()}`
				console.log(this.currentP);
		   		
		   	}
		   })
		
		},
	
		onReady() {
			// #ifdef APP-PLUS
				var currentWebview = this.$scope.$getAppWebview() //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
				setTimeout(() => {
					this.wv = currentWebview.children()[0]
				}, 1000); //如果是页面初始化调用时,需要延时一下
			// #endif
		
		},
		methods: {
			//处理H5向app通讯事件,监听H5
			 handleMessage(evt) { 
				 let data = evt.detail.data[0]
			        console.log('接收到的消息:' ,data);  
				  let type = data.type
				  if(type == '选择地点'){
					  console.log(type);
					  this.mapCenterPosition = data.mapCenterPosition
					  this.navto('/pages/selectSpot/selectSpot',{mapCenterPosition:this.mapCenterPosition})
				  }else if(type == '添加路线'){
					  this.linePosition = data.linePosition
					  this.navto('/pages/addLines/addLines',{linePosition:this.linePosition})
				  }else if(type == '添加区域'){
					  this.areaPosition = data.areaPosition
					  this.navto('/pages/addArea/addArea',{areaPosition:this.areaPosition})
				  }
					
			   },
			   //向H5页面发送消息
			   upH5Event(msg){
				   console.log(this.wv,'this.wv');
				   msg = JSON.stringify(msg)
				   this.wv.evalJS(`postJS(${msg})`);
			   }
		
			
		},
		// 原生导航监听函数
		onNavigationBarButtonTap(e) {
			//点击菜单图标
			if (e.index === 0) {
				mapMenuShow().then((res)=>{
					//res: 0:地图信息 , 1:图层列表, 2:标注图层
					if (res === 0) {
						uni.navigateTo({
							url:'/pages/mapInfo/mapInfo'
						})
						
					}else if(res === 1){
						uni.navigateTo({
							url:'/pages/coverageList/coverageList'
						})
						
					}else if(res === 2){
						uni.navigateTo({
							url:'/pages/labelMenu/labelMenu'
						})
					}
				})
				
			}
			//点击搜索图标
			if (e.index === 1) {
				let msg = {type:'擦玻璃'}
				this.upH5Event(msg)
			}
			
		},
		onBackPress(e) {
			//e.from === 'backbutton' 说明如果点击的是物理返回键或导航栏的返回键就进行以下操作
		      if (e.from === 'backbutton') {
		         uni.navigateBack()
		        //返回值为true 时,表示不执行默认的返回(默认返回上一页),执行自定义的返回
		 		//如果要限制必须写成true
		         return true;
		      }
		    },

	}
</script>
<style scoped>
</style>

2、vue项目打包的H5:会粘贴该引入的代码片段

1、index.html 引入uniapp必须的SDK文件,下面两个cdn文件,官网的介绍有坑,第一个cdn引入时候也是可以的,后面我看到另外一条好像更新的js文件,也引入了。

  <!-- uniapp 通信必须有的 -->
  <script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.2/index.js"></script>
  <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>

  <script>
document.addEventListener('UniAppJSBridgeReady', function() {  
    uni.getEnv(function(res) {  
        console.log('当前环境:' + JSON.stringify(res));  
    });  
});
</script>

2、在weview加载的那个vue页面中,直接声明全局方法,变量要跟vue的data里面的变量绑定,

<script>
var parmsObj;
 //接收app传递来的数据
   window.postJS = function(msg) {
                 msg = JSON.parse(JSON.stringify(msg))
                console.log(msg.type);
                console.log(parmsObj.title);
                parmsObj.title =' 再次测试uniapp'
            }

export default {
   data() {
      return {
         aa:{title:'uni'}
      }
   },
   created() {
       parmsObj = this.aa
   },
   methods: {
      //右下角菜单点击事件,H5向app通讯
      handleMenuEvent(index) {
         if (index == 1) {
          //这句就是H5向app通讯,必须引入SDK才能执行成功
            uni.postMessage({
               data: {
                  type:'选择地点',
                  mapCenterPosition: this.mapCenterPosition,
               },
            })
         } else if (index == 2) {
             uni.postMessage({
               data: {
                  type:'添加路线',
                  linePosition: [{lay:11,lng:22}],
               },
            })

         } else if (index == 3) {
              uni.postMessage({
               data: {
                  type:'添加区域',
                  areaPosition: [{lay:11,lng:22}],
               },
            })
         }
      },
     
   },
}
</script>

3、这是测试成功 截图,因为我是搞移动端的,页面打印要安装vconsole来查看

1、uniapp运行成功的控制台打印
在这里插入图片描述

2、H5监听APP传递过来的数据,控制台打印,必须通过Vconsole来查看
![![在这里插入图片描述](https://img-blog.csdnimg.cn/2c245c1e56104e1ea62d3b1e06c9bb9b.png](https://img-blog.csdnimg.cn/f51bdab02fa04fbd876a0c663abb228b.png

3、界面的响应式变量的绑定,监听到app的事件回调修改变量

![在这里插入图片描述](https://img-blog.csdnimg.cn/e05f1f12fa9b47d3af785a21f2a83bbf.png

![在这里插入图片描述](https://img-blog.csdnimg.cn/766fdce78a834433868e54f9f91df315.pn

### 在 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` 处理展示给终端使用者看。 综合运用前面提到的技术要点可以很好地满足此类复杂业务诉求。 --- ###
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值