这是一个翻遍全网都很难解决的bug,终于在我的反复尝试下,轻松实现。
先陈述我的问题:
有a和b两个项目,都是uniapp开发,a编译成小程序,b编译成h5,a中用webview嵌套b,如何实现b向a通信?
首先,官方提供的 uni.postMessage 目前实测很难生效,因为它有个限定条件:
但要解决问题,依然需要靠它这一点。话不多说,直接上代码:
1、A项目中【被编译为小程序或H5】
<template>
<view>
<web-view :src="webviewUrl" style="width:100vw;height:100vh;" @message="messageFn"></web-view>
</view>
</template>
<script>
export default {
name: "mall",
data(){
return {
webviewUrl: "xxxxx"
}
},
methods: {
// 监听嵌套的H5页面发过来的信息
messageFn(e) {
// console.log('收到iframe页面内容:', e.data)
if (!e.data.data) return;
if (e.data.data.arg !== 'back') return;
// 监听到web-view通知back,去处理你想做的事情,这里我是做了导航到首页
uni.navigateTo({
url: "/pages/index/index",
});
},
},
mounted() {
// #ifdef H5
// A项目运行在H5时,如果不加这句代码,真机运行的时候,就无法监听到message事件
window.addEventListener("message", this.messageFn, false)
// #endif
},
}
</script>
2、B项目中【被编译为H5】
B项目就是打包为H5,并将服务器地址作为 webviewUrl 放到A项目的 <web-view /> 中。
这里要注意,B项目中的postMessage想要让A项目(小程序端)直接收到,必须写在纯粹的html文件中,不能是通过webpack这类工具打包出来的项目。
所以需要在B项目中创建一个桥页 bridge.html(就是一个过渡页面,用完就跳走),页面我放在 /static/html/ 下代码很简单:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
桥页 - <span id="sp"></span>
</body>
</html>
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<script>
document.getElementById('sp').innerHTML = window.location.origin+'/gov/'
wx.miniProgram.navigateTo({
url: "/pages/index/index",
});
// 跳转页面随便跳,我是回退一层页面,因为回退页面也可以触发页面的销毁,使A项目中@message能生效
window.location.go(-1);
</script>
上面引入了 jweixin-1.4.0.js,是为了在小程序环境(B目前是被放在A这个小程序中)下可以直接使用微信的API。
最后就是B项目中原本你想要发送数据给A项目的页面中(也就是跳转去桥页的那个vue文件):
<template>
<view class="union_page">
<!-- 此页面用于跳转到bridge.html,通过页面销毁引起postMessage生效 -->
</view>
</template>
<script>
// #ifndef MP-WEIXIN
import web from '@/utils/js/uni.webview.1.5.4.js' // 自行下载
// #endif
export default {
mounted() {
// 以下代码当商城嵌入在H5时生效
// #ifndef MP-WEIXIN
const webview = web.webView
if (typeof webview !== "undefined") {
webview.postMessage({ data: "back" });
}
// #endif
// 以下代码当商城嵌入在小程序时生效
let msg = JSON.stringify({data: 'back'}) // 这里记得序列化
if(window){
window.parent.postMessage(msg, "*")
window.location.href = window.location.origin+'/static/html/bridge.html';
}
}
}
</script>
如此就完成啦!
我这里保留了最基础的代码,其他的业务代码就不展示出来了。uni.webview.1.5.4.js 和 jweixin-1.4.0.js 插件网上很多,大家可以自己百度。