uniapp编写微信小程序和H5遇到的坑总结
- 1、阻止事件冒泡
- 2、二维码生成
- 3、H5跨域配置
- 4、H5时,地址栏上添加版本号
- 5、H5时,tabBar遮挡部分内容
- 6、uniapp使用webview通信
- 6.1、uniapp编写的小程序嵌入h5之间的通信
- 6.1.1、小程序向h5发送消息
- 6.1.2、h5向小程序发送消息
- 6.2、h5和h5通信
- 6.2.1、A端向B端传递参数
- 6.2.2、B端向A端发送消息
- 7、使用webview嵌入h5导致双导航栏
1、阻止事件冒泡
使用uniapp开发微信小程序的时候,发现使用@click.stop
来阻止事件冒泡没有作用,点击了之后发现仍然会触发父组件或者祖先组件的事件。
在网上查阅,发现使用@tap.stop
才能阻止事件冒泡。
2、二维码生成
在网上找了很多,发现很多都不行(也有可能是代码没写对),最后是在uniapp的插件市场下载uQRcode插件,根据给出的案例,才完美解决了。
下面给处教程:
插件下载地址: uqrcode
1、 选中全部,搜索 “uqrcode”
2、选中如下插件
如果不是选中的同一个插件,点进入之后可以根据里面的教程案例编写代码,我将已这个插件为案例
3、下载压缩包
下载压缩包,解压后找到uqrcode.js文件,根据自己项目,复制到项目下。(我的是放在src/utils下的)
4、使用uqrcode.js
<template>
<view >
<view >
<canvas id="qrcode" ref="qrcode" canvas-id="qrcode"
:style="{width:`${qrcodeSize}px`, height: `${qrcodeSize}px`}"></canvas>
</view>
</view>
</template>
<script>
import uQRCode from "@/utils/uqrcode.js"
export default {
data() {
return {
qrcodeSize: 160,
text:'eoruw20230528'
}
},
mounted(){
this.getQRcodeHandle()
},
methods: {
// 获取二维码
getQRcodeHandle() {
uni.showLoading({
title: '二维码生成中',
mask: true
})
uQRCode.make({
canvasId: 'qrcode',
text: this.text,//二维码内容
size: this.qrcodeSize,
margin: 10,
success: res => {
console.log('qrcodeSrc = ' + res);
},
complete: () => {
uni.hideLoading()
}
})
},
},
}
</script>
3、H5跨域配置
网上查阅资料查阅了半天,发现大部分都只给出了一个步骤,结果都不行,最后发现还要改一个地方才会生效,真的是佛了呀!!
1、找到manifest.json,选择源码视图
2、找到h5,进入如下json配置
"h5": {
"devServer": {
"proxy": {
"/h5": {
"target": "xxxxxxxx",//请求数据的地址
"changeOrigin": true,
"ws": true,
"secure": false,
"pathRewrite": {
"^/h5": ""
}
}
}
},
}
3、修改baseURL(很重要,之前就是少了这一步,一直没配置成功)
let baseUrl = null;
if (process.env.NODE_ENV === 'development') {
baseUrl = '/h5'; //在请求数据的时候,会将/h5替换为配置的targer地址
// console.log('开发环境');
} else if (process.env.NODE_ENV === 'production') {
baseUrl =`https://${window.location.host}`;
// console.log('生产环境');
} else {
baseUrl = 'xxxxx';
// console.log('测试环境');
}
export default baseUrl;
配置完后记得重启项目才会生效
看网上查阅说,也可以自行在根目录下添加一个vue.config.js文件,进行跨域配置,就像vue项目那样配置。目前我还没有尝试这种方法,后面尝试了再继续完善文档吧。
4、H5时,地址栏上添加版本号
根据项目需求,从微信小程序切入webview跳转到这个H5项目时,根据不同版本,显示不同的页面内容。
在manifest.json文件中找到h5,添加如下配置:
"h5": {
"router": {
"mode": "hash",
"base": "h5/v/1.5.26/"
},
}
这样在允许时地址上就会有我们的版本号啦
5、H5时,tabBar遮挡部分内容
链接: 官方地址
由于在 H5 端,不存在原生导航栏和 tabbar,也是前端 div 模拟。所以tabBar会覆盖部分内容
会在 H5 端给 .content 元素增加一个 tabbar 的高度 的下边距, uni-app 默认给 tabbar 的高度是50px 。
已 .content为例:
.content{
padding-bottom: var(--window-bottom);
}
如果 50px 的高度还不够,可以使用下面的方法,在 tabbar 高度的基础上再增加 20px :
.content{
padding-bottom: calc(var(--window-bottom) + 20px);
}
6、uniapp使用webview通信
6.1、uniapp编写的小程序嵌入h5之间的通信
6.1.1、小程序向h5发送消息
这个比较简单,只需要在webview中的src做参数拼接就可以了。
1、创建webView
在小程序项目中添加了一个webView页面,代码如下
<template>
<view>
<web-view :src="src" @message="handleMessage"></web-view>
</view>
</template>
<script>
import {
mapGetters
} from "vuex"
import qs from "qs"
export default {
data() {
return {
src: ""
}
},
computed: {
...mapGetters(['user', 'school', 'token', 'school_token'])
},
onLoad(option) {
// decodeURI避免中文乱码,
this.src = "xxxxxxx?" + decodeURI(qs.stringify({
isView: 'true',
school: this.school,
token: this.token,
school_token: this.school_token,
user: this.user
}))
},
}
</script>
2、h5接收参数
我是在h5页面加载的时候接收的参数,也就是在APP.vue中onLaunch()中接收的
import qs from "qs"
onLaunch: function() {
console.log('App Launch')
const obj = qs.parse(window.location.href.split('?')[1]) || null;
if (obj && Object.keys(obj).length > 0) {
//如果有参数就对参数进行处理,但是有一点需要注意,如果传递过来的对象,最后一个属性值是字符串,后面值会自己跟一个 #/ ,具体为啥不知道,没有去找原因,反正我接收到的参数值是这样的,(我也是第一次用qs序列化参数,url拼接的是一个对象这样传参)
}
},
6.1.2、h5向小程序发送消息
这一块是真的坑,需要注意一下!!!!
链接: uniapp官方给出的案例
1、下载uni SDK
下载uni SDK的路径,需要将这个文件下载到项目中,我是命名为uni.webview.js,并放在static文件夹下
<script src="https://gitee.com/dcloud/uni-app/raw/dev/dist/uni.webview.1.5.3.js"></script>
2、修改index.html文件
在public下的index.html文件在添加如下代码,注意要放在<body></body>
后面
<script type="text/javascript">
var userAgent = navigator.userAgent;
if (userAgent.indexOf('AlipayClient') > -1) {
// 支付宝小程序的 JS-SDK 防止 404 需要动态加载,如果不需要兼容支付宝小程序,则无需引用此 JS 文件。
document.writeln('<script src="https://appx/web-view.min.js"' + '>' + '<' + '/' + 'script>');
} else if (/QQ/i.test(userAgent) && /miniProgram/i.test(userAgent)) {
// QQ 小程序
document.write(
'<script type="text/javascript" src="https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"><\/script>'
);
} else if (/miniProgram/i.test(userAgent) && /micromessenger/i.test(userAgent)) {
// 微信小程序 JS-SDK 如果不需要兼容微信小程序,则无需引用此 JS 文件。
document.write('<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"><\/script>');
} else if (/toutiaomicroapp/i.test(userAgent)) {
// 头条小程序 JS-SDK 如果不需要兼容头条小程序,则无需引用此 JS 文件。
document.write(
'<script type="text/javascript" src="https://s3.pstatp.com/toutiao/tmajssdk/jssdk-1.0.1.js"><\/script>');
} else if (/swan/i.test(userAgent)) {
// 百度小程序 JS-SDK 如果不需要兼容百度小程序,则无需引用此 JS 文件。
document.write(
'<script type="text/javascript" src="https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.18.js"><\/script>'
);
} else if (/quickapp/i.test(userAgent)) {
// quickapp
document.write('<script type="text/javascript" src="https://quickapp/jssdk.webview.min.js"><\/script>');
}
</script>
<!--上面的都是copy官方的,懒得再去删减修改了 -->
<!-- uni 的 SDK -->
<script type="text/javascript" src="<%= BASE_URL %>static/uni.webview.js"></script>
<script type="text/javascript">
// 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。
document.addEventListener('UniAppJSBridgeReady', function() {
webUni.getEnv(function(res) {
console.log('当前环境:' + JSON.stringify(res));
});
});
</script>
3、修改uni.webview.js
修改uni.webview.js中的内容。
默认自带的方法名为uni,会和本地的uni命名冲突。postMessage会报错不是一个function。
我改成了webUni。注意修改的地方有三处(我之前只改了一处,结果一直整不出来)
4、使用webUni.postMessage发送消息
可以通过点击事件来触发消息的发送
changeSchoolHandle() {
//如果想要点击按钮后,小程序退出H5页面,那么就在postMessage前进行路由跳转,具体支持的路由跳转方法,可以查看官方文档,
webUni.reLaunch({
url: '/pages/school/school'
})
webUni.postMessage({
data: {
type: 'backSchool'
}
})
},
//webView中使用@message对消息进行处理
<web-view :src="src" @message="handleMessage"></web-view>
注意:
- postMessage() 里,数据要放在 data 对象里。
- 注意触发的时机,只有 后退、组件销毁、分享 的时候,才会触发 web-view 的message事件。
- 使用 uni.postMessage() 方法,要改源码里的 uni 对象。此处我改为了webUni
6.2、h5和h5通信
h5 A 使用webview嵌入H5 B
6.2.1、A端向B端传递参数
也是通过url拼接的方式传递参数。同小程序向H5传递参数一样
6.2.2、B端向A端发送消息
这里就不能用uni.postMessage了,需要使用window.postMessage才行,这个跟iframe发送消息是一样的
A端
<view>
<web-view :src="xxxxxxxx"></web-view>
</view>
onLoad(option) {
this.viewLoadHandle()
},
methods: {
// #ifdef H5
viewLoadHandle() {
window.addEventListener("message", this.handleMessage);
},
// #endif
handleMessage(e) {
if (e.data.type === "message") {
//收到消息后,编写对应的逻辑处理代码
}
},
}
B端
window.parent.postMessage({
type: "message",
message: true,
}, url)//url为A端的地址
7、使用webview嵌入h5导致双导航栏
小程序嵌入了h5,导致双导航栏,看起来很不美观,所以需要隐藏一个导航栏。
本来想动态控制小程序导航栏是否显示,但是在网上一直没有找到合适的方法。所以最后只能在h5导航栏上做文章了。
在pages.json中配置
"globalStyle": {
"app-plus": {
"titleNView": false
}
},
这个设置,所有页面都不会显示导航栏了,又会造成一个新的问题:当存在页面跳转时,顶部没有返回按钮了。
所以就需要在需要返回功能的地方,自己写一个导航栏。因为我用的uView这个框架,直接套用 Navbar 自定义导航栏 就好了。
套用之后,发现导航栏会遮挡一部分内容,猜测导航栏是通过定位显示在顶部,所有才会遮挡部分内容(具体原因没有研究),给自定义导航栏下面的view盒子,添加了一个css样式:
margin-top: 50px;//
这样就只会显示一个导航栏啦!
注意:
通过webview跳转到h5后,顶部导航栏将进入h5后的第一个页面的导航栏标题作为默认标题。进入之后不管切换到h5的哪个页面,都不会改变。