最近参与了几个微信小程序的开发,其中有使用到小程序原生、uni-app和mpvue的方式开发。期间遇到了各种各样的坑以及一些小程序本身能力的限制。现归纳如下,让大家少走点弯路。
1.原生组件遮挡弹出框问题。(canvas,textarea等)
弹出框被原生组件遮挡的问题可以在弹出框中使用cover-view来代替view,但是这会导致弹出框的显示效果发生变化,需要修改弹出框的样式。更好的替代方法是:如果原生组件是canvas,可以在弹出对话框时用image代替canvas。例子如下:
布局
<image v-show="charImg" :src="charImgPath" class="charts"></image>
<canvas v-show="!charImg" canvas-id="canvasLineA" id="canvasLineA" class="charts" @touchstart="touchLineA"></canvas>
js
showCharImg(){
uni.canvasToTempFilePath({
x: 0,
y: 0,
destWidth: uni.upx2px(690),
destHeight: uni.upx2px(260),
width: uni.upx2px(690),
height: uni.upx2px(260),
canvasId: 'canvasLineA',
success: (res)=> {
this.charImg = true;
this.charImgPath = res.tempFilePath;
console.log("this.charImgPath="+this.charImgPath);
},fail(err) {
console.log(err);
}
},this);
},
如果原生组件是textarea则可以使用view来代替
<view v-if="getHiddenTextarea&¤t==itemIndex" class="remark-input">{{tempData[itemIndex].remark?tempData[itemIndex].remark:'请输入说明(选填)'}}</view>
<textarea v-else class="remark-input" v-model="tempData[itemIndex].remark" placeholder="请输入说明(选填)" auto-height type="text" maxlength=200 />
2.iOS全面屏底部黑色横条适配
之所以有这个问题,是因为iOS全面屏的高度是包含底部黑色横条的,而其他全面屏手机是不包括的。所以,如果有控件需要使用距离手机屏幕底部的绝对定位,则需要对iOS全面屏进行适配。目前判断是否为iOS全面屏比较好的做法是:先判断系统是否为iOS,再判断状态栏高度是否大于20。目前非全面屏iPhone的状态栏都是20px,全面屏iPhone为44px。现在不能简单地判断手机名字是否带iPhoneX来适配了,因为出了iphone 11。
function getiOSFullScreen(callback){
wx.getSystemInfo({
success: (res)=>{
if (res.system.search('iOS') != -1&&res.statusBarHeight>20) {
callback(true);
}else{
callback(false);
}
}
})
}
3.iOS下日期格式转换问题
在使用如下日期格式转换为时间戳时,苹果手机会转换失败。
new Date("2020-08-17 15:57:27").getTime(); //苹果手机结果为NaN,安卓能正常转换为时间戳
解决方法:将"yyyy-mm-dd hh:mm:ss"转为"yyyy/mm/dd hh:mm:ss",然后再使用上面的方法,代码如下:
let str = "2020-08-17 15:57:27".replace(/-/g, '/')
let timestamp = new Date(str).getTime();
4.input输入框的问题
在iOS下,input输入框会出现一些意想不到的问题,这是微信小程序的老bug了。当页面上有多个input输入框,来回切换获取焦点的输入框时,有时会出现获取不到焦点的问题。在swiper组件中使用input组件回来滑动时,部分iOS手机点击输入框会获取不了焦点。一个比较好的做法是:当输入框失去焦点时,使用view来代替输入框。需要输入时,再替换回来。
5.textarea的问题
在iOS下,textarea有内边距。即使使用padding:0,内边距依然存在。这是微信小程序的bug,目前还没解决。
6.保存文件到本地以及预览文件的问题
小程序保存文件到本地有大小限制,目前最多保存10m文件。本地文件总存储空间超过10m之后,将无法下载文件到本地。
在最近开发中,遇到这样一个场景:一个企业内部的小程序,里面有个功能,提供了很多文件和学习资料给员工学习。
一开始我是先把文件下载下来,再使用wx.openDocument()这个api打开文件。下载了几个文件之后,发现其他文件就下载不成功了。后来才发现微信小程序有存储空间大小的限制。
然后,我干脆不把文件下载到本地,直接下载到临时目录。如下图,出入filePath字段时,下载文件到本地,不传时下载到临时目录。详细可以阅读官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/network/download/wx.downloadFile.html
下载完成之后,使用wx.openDocument()传入filePath字段就可以打开文件了。但是,这里有个坑需要注意的:wx.openDocument()的filePath字段需要的是一个本地路径,也就是本地文件的路径。如果使用临时路径,苹果手机是打不开文件的,安卓能正常打开。
因为这个原因,我还是需要把文件下载到本地后,再使用wx.openDocument()打开文件。但是下载到本地的文件超过10m后就不能下载了。这就不得不在每次下载新文件之前,先把保存在本地的文件清空。
删除文件这里也有需要注意的地方,小程序提供了两个删除文件的api,分别是:FileSystemManager.removeSavedFile()和FileSystemManager.unlink()。在使用中发现,FileSystemManager.removeSavedFile()这个api并不能成功删除本地文件,于是我使用FileSystemManager.unlink()这个api。方法如下:先使用FileSystemManager.readdir()方法传入小程序本地用户路径拿到所有本地文件路径,然后遍历传入本地文件路径,使用FileSystemManager.unlink()方法删除文件。
removeAllFile() {
return new Promise((resolve,reject)=>{
let fm = wx.getFileSystemManager();
const basepath = `${wx.env.USER_DATA_PATH}`
fm.readdir({
dirPath: basepath, /// 获取文件列表
success(res) {
console.log(res)
res.files.forEach((val) => { // 遍历文件列表里的数据
console.log(val)
fm.unlink({
filePath: basepath + '/' + val
});
})
},
fail(err) {
console.log(err)
},
complete() {
console.log('complete')
resolve("");
}
})
});
},