书写背景
从接触到开发小程序,
也有一段时间了。
想新建一个帖子,
借此总结复盘一下自己踩过的坑,
和含泪背锅的经历。
背锅标签
- wx.previewImage 不能禁用用户保存图片
- ios 播放音频偶尔会出现错误
- UploadTask.onProgressUpdate 进度回调不准确
- “右滑手势返回”能力调整
- 微信 7.0.12 调用 wx.scanCode 后无 path 返回
- video 在 scrollView 中使用的俩个 bug
- video 退出全屏播放后,安卓会回到顶部?
- canvasContext.draw 回调 ios 第二次不执行
应用场景
每个页面尽量重新调用接口
这样做的好处是降低耦合,
页面与页面之间是一个非常脆弱的关联。
因为谁也说不准未来的需求,
会不会一时兴起要“空降”这个页面。
那么如果这个页面依赖于之前的缓存或者其他处获取 Redux 等全局的数据,
最后的结果肯定是惨痛的修修补补。onLoad/ onShow 生命周期
onLoad 的声明周期只用来处理页面传参。
onShow 的声明周期用来调用接口初始化数据。
如果二者混用,那么绝逼会由于接口异步的调用,
导致某些数据依赖数据没获取到就执行下一步,
从而使程序出现一堆偶现且莫名其妙的错误。自定义封装的顶部导航
关于自定义的导航有两点想说一下:
一是,fixed 样式兼容。
当处于 fixed 样式的时候,
最好能实现个空格高度来占位文档流。
这样可以兼容用 fixed 的页面和不用 fixed 的页面。
有了占位之后,可以保证 fixed 的页面不会被搞垮掉。
另外也没必要让每个页面都要特意做个 padding-top。
这个 padding-top 还需要根据机型来判断高度。
所以最好还是都封装在顶部导航组件里来处理这个脏活是最好了。
二是,返回按钮劫持事件。
由于微信版本的更新,
在真机使用小程序时候,
可以通过右划左屏幕边缘,来完成快捷返回上一页的交互。
这个交互且无法关闭。
(可能为了照顾大屏手机 or 最小化小程序交互?)
这样相当于跨过了点返回按钮才返回的交互。
如果再点击返回按钮时候做了逻辑处理,
那么就很容易给未来的自己挖坑。
所以,最好还是通过 重定向 的跳转方式,
稳定的来维护我们的路由堆栈。关于接口参数的传递
比如封装接口,需要传值的时候,
需要多少参数,就给封装函数参数设置多少个变量。
举个例子。1
2
3
4
5
6
7
8
9
10
11
12
13const queryAppInfo = async (
memberId?: string,
appId?: string,
timestamp?: string
) => {
const params = {
memberId,
appId,
timestamp,
};
const res = await CloudFetch.callFunction("fetchAppInfo", params);
return res.data.data[0];
};而有些参数是可选传参。比如我们不需要传递 appId 的时候,
外部调用的时候就会很难看1
queryAppInfo("007", , '123');
那么,个人认为还是在调用接口的地方处理好参数对象,
直接将参数对象传入封装的函数中,1
2
3
4
5const param = {
memberId: "007",
timestamp: "123",
};
queryAppInfo(param);这样看起来比较规范,数据也会比较安全。
弹出弹窗效果的实现
无论是模态对话框,还是弹出提示性的对话框。
虽然看起来只是弹出个对话框。
不过最好底部加一层蒙板,1
2
3
4
5
6
7
8.mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.2);
}无论是透明或者有颜色。
这样不仅可以在蒙板上完成,阻止事件冒泡。
也可以在蒙板上完成,点击其他部分关闭提示对话框。应用系的组件,要清晰回调函数
比如:登录、授权组件,回传事件需要明确。1
2
3
4
5
6success: (res) => {
// TODO:...
};
fail: (err) => {
// TODO:...
};保证性能,谨慎接口调用
如果说前端都可以判断到,条件是不符合的,
那么无需做无用功,去再调用接口。公共组件内的数据建议还是通过组件传值来取
如果过度依赖 Redux 中的数据,
就会导致该模块只能适用当前模块。
以至于后期其他模块无法复用。Html 模板内尽可能的使用自闭合标签
在多方因素的作用下:
面条型的代码量的增加,
个别情况下的书写习惯,
线上 bug 临时写一笔赶工,
代码过长,缩进捋不清除。
在这种情况下,是很容易将一些代码混进标签内,
进而引发一些莫名其妙的错误,而且很难定位具体问题。
所以尽量使用自闭合标签来避免这些问题。JSON.parse 的坑
JSOM.stringify 和 JSON.parse 是对序列化很有效的方法。
可供使用的场景也非常频繁。
JSOM.stringify 还好说,转换为字符串问题都不是很大。
JSON.parse 相对而言就要谨慎使用。
将一个 JSON 字符串转换为对象,
可是如果参数传入一个非 JSON 字符串的话,就会导致报错。
所以在使用 JSON.parse 的时候,一定要有一层保护。
即使传入的参数不是个正经值的时候,
传入个’{}’默认字符串以保证程序不至于报错。wx.scanCode() 返回结果的坑。
调用微信小程序官方 API
wx.scanCode() 返回值的 path 字段,
竟然有时候存在,有时候就没有。
对照官方文档之后,看到官方给出的说法是1
当所扫的码为当前小程序二维码时,会返回此字段,内容为二维码携带的 path
不过有的时候也没有,只能通过 result 字段存储两份数据。
在扫码成功后,能读取成功哪个字段就取哪个字段的数据。微信小程序 scroll-view 组件实现横向滚动的坑
经过测试,
发现要想实现横向滚动,不仅在组件设置对应属性字段,
还需要 CSS 中满足两个条件:- 外部 scroll-view 容器设置
1
white-space: nowrap;
- 每个滚动子项需要设置
1
display: inline-block;
在 ScrollView 中使用 Canvas 组件
会有很多异常的情况出现,比如真机情况下,渲染出来的图片需要屏幕左上角闪一次才会回到期望渲染位置。
解决方案,尽量不要将 Canvas 放到 ScrollView 里。生成出来的图片,尽量通过 Canvas 转为 Base64,然后再通过 Base64 渲染到 Image 标签上。模拟器 canvas 绘制海报的时候 canvasContext.draw 回调第二次不执行。
如下代码所示,
第一次执行的时候该段函数 1、2、3 都可以执行,
不过第二次则只会执行 1、2,
3 则不会再进入。真机暂未发现该问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32console.log("updateCanvasShare1", srcQRCode, strShareContentUrlTmp);
await drawCanvasShare(
canvasShare,
strShareContentUrlTmp,
srcQRCode,
strSharePosterText || sharePosterText,
2
);
console.log("updateCanvasShare2", srcQRCode, strShareContentUrlTmp);
canvasShare.draw(false, () => {
console.log("updateCanvasShare3", srcQRCode, strShareContentUrlTmp);
// Taro.hideToast();
Taro.canvasToTempFilePath({
x: 0,
y: 0,
width: PANEL_SHARE_WIDTH * 2,
height: PANEL_SHARE_HEIGHT * 2,
destWidth: PANEL_SHARE_WIDTH * 2,
destHeight: PANEL_SHARE_HEIGHT * 2,
fileType: "jpg",
canvasId: "canvas-share",
success: (resToCanvas) => {
console.log("canvasToTempFilePath success.", resToCanvas);
setSharePhotoUrl(resToCanvas.tempFilePath);
},
fail: (errToCanvas) => {
console.log("canvasToTempFilePath fail.", errToCanvas);
setShowBtnRefresh(true);
Taro.showToast({ title: "生成海报失败", icon: "none" });
},
});
});小程序检测版本更新 wx.getUpdateManager 的一些坑。
如下为官方的示例代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21const updateManager = wx.getUpdateManager();
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
console.log(res.hasUpdate);
});
updateManager.onUpdateReady(function () {
wx.showModal({
title: "更新提示",
content: "新版本已经准备好,是否重启应用?",
success: function (res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate();
}
},
});
});
updateManager.onUpdateFailed(function () {
// 新版本下载失败
});如果在触发
更新提示
弹窗后,点击确认,
此时,会弹出小程序需要重启以使用最新功能
弹窗,点击知道了
即可重启小程序。可如果不点确认,而业务逻辑异步出现跳转页面的逻辑,更新逻辑就会被冲掉。
而第二次进入小程序的时候,在触发更新提示
弹窗后,点击确认,也不会出现小程序需要重启以使用最新功能
弹窗,
只能默默等待小程序自动更新,或者手动杀掉小程序,清除缓存。实机 css 动画超出圆角 overflow:hidden 范围
真机的情况,css animation 动画,在圆角 overflow:hidden 标签内,显示的内容会超出范围。
解决方法:
调整父级元素的层级即可。
实机 css 动画超出圆角 overflow:hidden 范围iOS 上 video 位于 scrollView 内部时,全屏后返回,scrollView 自动滚动到顶部
微信小程序当前版本的表现即是如此,
目前解决方式即是 video 的标签,不要放到 scrollView 内部。(scrollview 的坑太多)
iOS 上 video 位于 scrollView 内部时,全屏后返回,scrollView 自动滚动到顶部
后记
如果后续有想到的会随时更新。