记录下 uni-app WebView 组件通信的相关问题?
项目中有需要嵌入其他 H5 的页面的业务需求。
官网的 web-view 文档中介绍还是挺简单的,但其中还有一些不必要的坑。
在社区有这样一篇帖子 在 web-view 加载的本地及远程 HTML 中调用 uni 的 API 及网页和 vue 页面通讯,浏览量已经 5w 左右,看来还是有很多人有这样的需求。
虽是一篇过时的帖子,其中 sdk 的版本也过低,已经无法使用,但是仍有参考的价值,能借鉴之前的坑。
开始的需求是在 APP 中嵌入第三方的 H5 页面。
APP 端使用
在 uni-app 中使用方法很简单。
<web-view
v-if="srcUrl"
:src="srcUrl"
@message="reciveMessage"
@onPostMessage="recivePostMessage"
>
</web-view>
直接使用 web-view
组件,将链接设置为 src
。
那么引入了之后如何进行通讯?这个时候就得看文档了。
在 <web-view>
加载的 HTML 中,添加以下代码:
// 引入 uni-app 的 sdk
<script
type="text/javascript"
src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"
></script>
新建一个简单 webview.html
文件,引入上面的 sdk.js 作为例子。
<!-- webview.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>webview</title>
</head>
<body>
<div>
<p id="messageText"></p>
<div class="btn-list">
<button class="btn btn-red" type="button" id="clickMe">
点击我给 APP 传递参数
</button>
</div>
</div>
<script
type="text/javascript"
src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"
></script>
<script type="text/javascript">
window.jsfunction = function (data) {
let canshutype = typeof data;
let mes = typeof data == "object" ? JSON.stringify(data) : data;
alert("收到参数" + canshutype);
document.getElementById("messageText").innerHTML =
"恭喜你,接收到你的参数n,参数是" + canshutype + "参数如下:n" + mes;
console.log("data", data);
};
document.addEventListener("UniAppJSBridgeReady", function () {
document
.getElementById("clickMe")
.addEventListener("click", function () {
let data = {
user_id: "ys123456",
user_token: "67374b30-cac6-4efb-adc9-88231b9ac44c",
user_info: {
name: "Iuhuy",
avatar:
"http://thirdwx.qlogo.cn/mmopen/vi_32/EURpungADj4vP3UczBVvD1DcEUt9q7WFqc6mZlSZoXoS9PyaPicnX8pjmic0rLbmwYCSa247gibINd1dWr0ic1QTvw/132",
},
};
console.log("给 uni-app 发送数据", data);
uni.postMessage({
data: data,
});
});
});
</script>
</body>
</html>
可以使用 npm 包 http-server 起一个本地服务。
本地起一个 server:
在 web-view
组件直接引入:
<web-view
src="http://192.168.1.56:8081/webview.html"
@message="reciveMessage"
@onPostMessage="recivePostMessage"
></web-view>
手机运行点击按钮,在 HBuilderX
控制台中就能看到接收到的数据。
手机端收到的数据如下,这样是能收到数据的:
H5 端使用
上面是 APP 端的,H5 并不能收到参数。uni-app 打包成 H5 怎么接收参数呢?
开始也很纳闷,然后看了下官方的文档,web-view 组件的浏览器内核说明。
提到 H5 端的 web-view 其实是被转为 iframe 运行,使用的是当前的浏览器
,那么就通过 iframe 来通讯不就好了嘛。APP 端和 H5 进行条件编译一下,分别使用不通方式:APP-webview;H5-iframe。
经验证,结果也是可行的。在需要加载链接的地方进行条件编译,分别把链接带到指定页面。
/**
* 跳转到加载页面
*/
gotoGamePage(item) {
// #ifdef APP-PLUS
uni.navigateTo({
url: "../mind/showGame?uri=" + item.uri,
});
// #endif
// #ifdef H5
uni.navigateTo({
url: "../mind/showGameIframe?uri=" + item.uri,
});
// #endif
},
// showGameIframe.vue
<view>
<iframe
id="iframe"
class="viewiframe"
src="http://192.168.1.56:8081/webview.html"
ref="iframe"
@onload="onLoad"
>
</iframe>
</view>
mounted() {
// 接受子页面发来的信息
window.addEventListener("message", this.ReceiveMessage);
//console.log("------>",this.url)
},
methods: {
onLoad(option) {
console.log("---------------->onLoad", option);
},
ReceiveMessage(event) {
// console.log("ReceiveMessage$$$", event);
if (event.data && event.data.data && event.data.data.arg) {
console.log("iframe 参数 event.data:", event.data.data.arg);
}
},
SendMessage() {
let str = toolTimer.formatTime(new Date(), "yyyy-MM-dd");
let data = {
action: 66,
time: str,
};
document.getElementById("iframe").contentWindow.postMessage(data, "*");
},
},
也是能收到参数的:
小程序和其他端没有试过,有小程序和其他端开发需求的小伙伴可以自己再试试。