近期在使用uniapp开发一个app中过程中因为要用户卫星地图,uniapp自带的地图组件无法满足需求,因此,想要了webview引入一个html页面来实现解决这个问题。但是在vue页面和webview引入的页面双向通信过程中,遇到了问题,html页面可以很方便的给vue页面发送信息,但无法接收到信息,尝试了很多方法都失败了,官网的实例给了我灵感,下面就是我在具体实践过程中的一些小小心得体会:当然在此之前最后先阅读一下官方文档,web-view | uni-app官网,以此为基础,可以避开不少坑
1、注意事项:
- app页面必须是nvue,否则服务调用到 evalJs方法
- nvue页面监听webview推送数据要用,@onPostMessage这个方法,提一句vue页面使用@message方法
- 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)`
);