记录下 uni-app WebView 组件通信的相关问题?
项目中有需要嵌入其他 H5 的页面的业务需求。
官网的 web-view 文档中介绍还是挺简单的,但其中还有一些不必要的坑。
在社区有这样一篇帖子 在 web-view 加载的本地及远程 HTML 中调用 uni 的 API 及网页和 vue 页面通讯,浏览量已经 5w 左右,看来还是有很多人有这样的需求。
虽是一篇过时的帖子,其中 sdk 的版本也过低,已经无法使用,但是仍有参考的价值,能借鉴之前的坑。
开始的需求是在 APP 中嵌入第三方的 H5 页面。
APP 端使用
在 uni-app 中使用方法很简单。
v-if="srcUrl" :src="srcUrl" @message="reciveMessage" @onPostMessage="recivePostMessage"></web-view>
直接使用 web-view
组件,将链接设置为 src
。
那么引入了之后如何进行通讯?这个时候就得看文档了。
在 加载的 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 作为例子。
<html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>webviewtitle> 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
组件直接引入:
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 id="iframe" class="viewiframe" src="http://192.168.1.56:8081/webview.html" ref="iframe" @onload="onLoad" > 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, "*"); },},
也是能收到参数的:
小程序和其他端没有试过,有小程序和其他端开发需求的小伙伴可以自己再试试。