uniapp中webview双向通信问题

近期在使用uniapp开发一个app中过程中因为要用户卫星地图,uniapp自带的地图组件无法满足需求,因此,想要了webview引入一个html页面来实现解决这个问题。但是在vue页面和webview引入的页面双向通信过程中,遇到了问题,html页面可以很方便的给vue页面发送信息,但无法接收到信息,尝试了很多方法都失败了,官网的实例给了我灵感,下面就是我在具体实践过程中的一些小小心得体会:当然在此之前最后先阅读一下官方文档,web-view | uni-app官网,以此为基础,可以避开不少坑

1、注意事项:

  1. app页面必须是nvue,否则服务调用到 evalJs方法
  2. nvue页面监听webview推送数据要用,@onPostMessage这个方法,提一句vue页面使用@message方法
  3. html页面必须要引入uni.webview.1.5.6.js,当然1.5.6是当前最新版本,具体版本以官网为准

2、实现过程:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    ...
  </head>
  <body>
    <noscript>
      <strong>Please enable JavaScript to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
  <!-- uni 的 SDK -->
  <!-- 需要把 uni.webview.1.5.6.js 下载到自己的服务器 -->
  <script type="text/javascript" src="https://gitcode.net/dcloud/uni-app/-/raw/dev/dist/uni.webview.1.5.6.js"></script>
  <script>
    document.addEventListener('UniAppJSBridgeReady', function() {
      uni.webView.getEnv(function(res) {
        console.log('当前环境:' + JSON.stringify(res));
      });
      // uni.webView.navigateTo(...)
    });
  </script>
</html>

nvue webview通信示例

<template>
	<view>
		<web-view ref="webview" class="webview" @onPostMessage="handlePostMessage"></web-view>
		<button class="button" @click="evalJs">evalJs(改变webview背景颜色)</button>
	</view>
</template>

<script>
	export default {
		data: {
		},
		methods: {
			// webview向外部发送消息
			handlePostMessage: function(data) {
				console.log("接收到消息:" + JSON.stringify(data.detail));
			},
			// 调用 webview 内部逻辑
			evalJs: function() {
				this.$refs.webview.evalJs("document.body.style.background ='#00FF00'");
			}
		}
	}
</script>

上面是官网实例,这个实例确实可以修改html的背景图片,但是我的业务环境要复杂许多,这个实例远远不能满足,尝试许久都失败了,直到

document.body.style.background ='#00FF00'

这句代码激发了我的灵感,app中可以调用到document绑定的方法,既然如此我们就可以在html中document监听一个自定义方法,app中调用这个方法就可以了

<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		
	</head>
	<body>
		
	</body>

	<script type="text/javascript" src="./dist/uni.webview.1.5.6.js"></script>
	
	<script>
		document.addEventListener('UniAppJSBridgeReady', function() {
            uni.postMessage({
				data: {
					action: 'test',
				}
			});
			document.addEventListener("custom", function(e) {
				
			})

		});
	</script>
</html>

nvue调用

<template>
	
		
		    <web-view
				style="flex: 1"
				ref="webviewRef"
				src="../../hybrid/html/map.html"
				:update-title="false"
				@onPostMessage="mapMessage"
			></web-view>
	
		
</template>

<script setup>
import { nextTick, onMounted, ref } from 'vue';
const webviewRef = ref();

// 接收webview消息
function mapMessage(evt) {
	console.log('evt=========', evt.detail.data);
	
}

function sendMsg(command) {
	nextTick(() => {
		let command_text = JSON.stringify(command);
		webviewRef.value.evalJs(
			`let msE = new CustomEvent('custom', {detail: ${command_text}});document.dispatchEvent(msE)`
		);
	});
}

</script>

<style lang="scss" scoped>

</style>

 最主要就是靠这一句, {detail: ${command_text}}是传递的参数可以自行调整

webviewRef.value.evalJs(
			`let msE = new CustomEvent('custom', {detail: ${command_text}});document.dispatchEvent(msE)`
		);

如果你不需要传递参数可以用

webviewRef.value.evalJs(
			`let msE = new Event('custom');document.dispatchEvent(msE)`
		);

 

### UniApp WebView 组件与原生应用之间双向通信的方法 在UniApp项目中,当需要通过`<web-view>`组件加载外部网页并与其进行数据交换时,确实会遇到一些挑战。对于Vue页面向HTML页面传递信息以及相反方向的操作,官方提供了一定的支持机制。 #### HTML 页面接收来自 Vue 的消息 针对从Vue侧主动推送数据至WebView内部展示的内容这一情况,可以通过调用`webviewContext.postMessage()`函数完成操作[^1]。此方式允许宿主环境(即包含Web视图的应用部分)向其子级的Web资源发送自定义事件连同附加的数据负载一起发出通知。 ```javascript // 假设已经在合适的地方获取到了对应的上下文对象 const webViewCtx = this.$refs.webview.getContext(); webViewCtx.postMessage({ type: 'someType', payload: { key: value } }); ``` 上述代码片段展示了如何构建一个简单的跨进程间的消息传输流程,在这里`type`字段用于标识不同类型的动作以便于接收方能够据此作出相应处理;而`payload`则承载着实际待共享的信息体。 #### 向 Vue 发送消息 为了让HTML页面能顺利地反馈信息回给Vue层面上下文中,则需依赖JavaScript接口注册的方式达成目标。具体来说就是在创建Web View之前预先设定好一系列可供前端调用的方法名及其关联逻辑,之后便可在任意时刻借助这些公开暴露出来的API来进行回调请求了[^2]。 ```html <!-- 这里是位于WebView中的H5页面 --> <script> function sendMessageToNative(data){ window.uniwebview.sendMessage(JSON.stringify(data)); } </script> <button onclick="sendMessageToNative({action:'openMap',params:{location:'Beijing'}})">Open Map App</button> ``` 与此同时,还需确保在启动该容器前已经声明好了相应的监听器: ```javascript // 定义在Vue组件内的methods选项卡之下 mounted(){ plus.webview.currentWebview().evalJS(` (function() { window.uniwebview = {}; window.uniwebview.sendMessage = function(msgStr){ var msgObj=JSON.parse(msgStr); webviewContext.evalScript('handleMessageFromWeb('+ JSON.stringify(msgObj)+')'); }; })(); `); }, methods:{ handleMessageFromWeb(messageObject){ console.log(`Received message from Web:${messageObject.action}`); switch(messageObject.action){ case "openMap": // 执行打开地图应用程序的相关业务... break; default: alert("Unknown action"); } } } ``` 以上便是基于uni-app框架下的两种主要途径来建立两者间的联系通道,并实现了较为完整的互动模式。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值