uniapp 小程序 web-view 打开H5页面传参以及调用postMessage回传参数
-
uniapp 运行微信小程序,在小程序内利用 web-view 打开H5页面进行数据流转的总结。
-
首先做点准备工作,官网明确的说了小程序是不支持本地的,那怎么进行调试呢,这里也简单,我们使用 node.js 起一个本地服务器,然后在 uniapp 中使用。
-
这里直接把 js 代码贴出来,直接复制就可以了
const http = require('http'); const fs = require('fs'); const path = require('path'); function startServer() {const server = http.createServer((req, res) => {// 设置通用响应头res.setHeader('Content-Type', 'text/html; charset=utf-8');let stream;switch (req.url) {case '/h5.html':// 首页内容filePath = 'h5.html';break;} if (filePath) {// 获取文件流stream = fs.createReadStream(path.join(__dirname, filePath), 'utf8');// 监听错误事件stream.on('error', (err) => {console.error('Stream error:', err);// 重写响应头res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });res.end('500 Internal Server Error');});stream.pipe(res);} else {// 如果没有设置文件路径,发送404响应res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });res.end('404 Not Found');}}); server.listen(3000, '127.0.0.1', () => {console.log('Server is listening on port 3000');}); } module.exports = { startServer }; startServer()
-
- node本地服务
-
然后这个地方要注意一下,这里的 html 文件就是一会要在内嵌在小程序中的文件,而且要注意,这个文件要跟 node.js 在同一级文件夹内,然后那个 case 就是我们要访问的路径,
运行,出现这个信息就是运行成功了。
uniap 小程序 web-view
-
这里我们要创建两个文件,index和auto
-
index 文件中代码如下,这里我们写一个按钮然后跳到 auto 然后在auto文件中内嵌H5页面,同时监听 login 事件,拿到 auto 的页面提交的参数。等下会解释为什么这么做。
<template><view class="content"><view class="text-area"><text class="title">{{ title }}</text></view> <view><button @click="clickUrl">点击跳转H5</button></view> <view>h5页面传过来的参数:{{ paramsH5.userName }} {{ paramsH5.message }}</view></view> </template> <script> export default {data() {return {title: "微信小程序页面1",paramsH5: { userName: "", message: "" },};},onLoad() {uni.$on("login", (usnerinfo) => {this.paramsH5 = usnerinfo;});},onUnload() {// 移除监听事件uni.$off("login");},methods: {clickUrl(params) {uni.navigateTo({url: "/pages/auto/index",});},}, }; </script> <style> .content {display: flex;flex-direction: column;align-items: center;justify-content: center; } .logo {height: 200rpx;width: 200rpx;margin-top: 200rpx;margin-left: auto;margin-right: auto;margin-bottom: 50rpx; } .text-area {display: flex;justify-content: center;margin: 24rpx;font-size: 48rpx;font-weight: bold;color: black; } .title {font-size: 36rpx;color: #8f8f94; } </style>
-
auto 文件中代码如下,这里的 http://127.0.0.1:3000/h5.html?name=iadajelkljwieqjeojqoi1j231j 就是我们访问H5页面的链接,问号后面就是向H5页面传递的参数。目前网上小程序对H5页面传参数的方法基本都是通过 url 的方法,其他方法需要各位自行查阅了,这里的 @message="handleMessage" 就是拿到H5页面传回来的数据,拿到之后我们通过 uni.$emit 提交到 index 页面展示。
<template><view class="content"><web-view@load="loadSuccess"@error="loadError"src="http://127.0.0.1:3000/h5.html?name=iadajelkljwieqjeojqoi1j231j"@message="handleMessage"></web-view></view>
</template><script>
export default {data() {return {title: "微信小程序页面2",};},onLoad() {},methods: {handleMessage(data) {console.log("接收到的消息:", data.detail.data);uni.$emit("login", {userName: "unier",message: data.detail.data,});},
loadSuccess() {console.log("加载成功");},loadError() {console.log("加载失败");},},
};
</script><style>
</style>
-
H5页面代码如下,这里要注意,调用完 uni.postMessage({ action: 'someAction', data: 'someData' }) 回传数据后,要调用 uni.navigateBack({ delta: 1 }); 因为官网是这样解释的 ( 会在特定时机(后退、组件销毁、分享)触发并收到消息。 ),所以要调用后退,不然 @message="handleMessage" 无法接收消息,还有 JS-SDK 的引入,这个引入的方法官网都有,我这边是只有微信,所以就只引了微信的,注意引入的顺序,uni sdk 放到body下面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>H5页面</title><style>.title {font-size: 24px;font-weight: bold;text-align: center;}
.wxParams {font-size: 24px;font-weight: bold;text-align: center;margin: 12px;}
#paramsText {text-align: center;}</style>
</head>
<body><div id="app"><h1 class="title">这是一个H5页面</h1><div class="title"><button id="backBtn">传参返回微信小程序</button></div>
<div class="wxParams">小程序页面传过来的参数:</div><div id="paramsText"></div></div>
<!-- 微信 JS-SDK 如果不需要兼容小程序,则无需引用此 JS 文件。 --><script type="text/javascript">document.write('<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"><\/script>');</script>
</body><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">// 获取小程序中传过来的参数并展示document.querySelector('#paramsText').innerHTML = getQuery('name')function getQuery(name) {// 正则:[找寻'&' + 'url参数名字' = '值' + '&']('&'可以不存在)let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");let r = window.location.search.substr(1).match(reg);if (r != null) {// 对参数值进行解码return decodeURIComponent(r[2]);}return null;}// 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。document.addEventListener('UniAppJSBridgeReady', function () {console.log('UniAppJSBridgeReady加载完成');uni.getEnv(function (res) {console.log('当前环境:' + JSON.stringify(res));});
document.querySelector('#backBtn').addEventListener('click', function (evt) {
uni.postMessage({ action: 'someAction', data: 'someData' })uni.navigateBack({ delta: 1 });});});
</script>
</html>
-
最终效果
-
最后说一下为什么创建两个文件,为什么在auto中通过监听和提交数据的形式拿到H5页面传过来的参数,首先,笔者最开始也是在一个文件中使用web-view组件,但是发现无论怎么做 H5页面 uni.navigateBack({ delta: 1 }) 这行代码就是不生效,,,不生效就无法触发@message,就拿不到H5页面的参数,浪费了好长时间,最后才发现不是不生效,而是在一个页面中没有能 navigateBack 返回的页面,,,,就无法触发@message。
-
最后分两个文件,这样就能 navigateBack 然后触发 @message 了,也正是因为这样,我们的 auto 中嵌套的H5页面在执行 uni.navigateBack({ delta: 1 }) 这段代码之后,会回到index页面。所以使用监听和提交数据的方式拿到H5页面的数据,这样就能在index文件中展示了。好了,到这里就结束了,记录我的踩坑之旅。