本文从小程序框架、 api 、组件、应用四个方面入手,说明在开发过程中遇到的问题,并给出处理方案。
小程序虽然具有相对完善的文档,但难免文档中会有解释不清晰,不易被人发现,甚至未曾提及的问题。本文从具体的业务场景出发,汇总笔者在原生小程序日常开发中遇到的常见问题,并给出相应的解决方案,希望能够将这些细节经验分享给需要的童鞋。
框架
运行机制与更新机制
运行机制:
小程序启动会有两种情况,一种是「冷启动」,一种是「热启动」。 假如用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需将后台态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。
- 小程序没有重启的概念。
- 当小程序进入后台,客户端会维持一段时间的运行状态,超过一定时间后(目前是5分钟)会被微信主动销毁。
- 当短时间内(5s)连续收到两次以上收到系统内存告警,会进行小程序的销毁。
更新机制:
小程序冷启动时如果发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一次冷启动才会应用上。 如果需要马上应用最新版本,可以使用 wx.getUpdateManager API 进行处理。
虽然文档中有对这一部分进行说明,但是隐蔽比较深,还是需要重点说明一下,理解运行机制就可以解释为什么刚关闭的小程序打开之后还能保存之前的状态,理解更新机制就明白新发版的小程序为什么需要删除旧的版本再下载新的版本再能有新版的内容了。
如何清除小程序缓存呢?
- 通过太空囊’…’按钮—打开调试—console—wechat—wx.clearStorage()方法清除,此方法删除 storage 中的数据。
- 通过微信的”发现”tab签—小程序—长按或者右滑删除指定小程序,此方式彻底卸载该小程序,也就清除了所有内容,包括 storage 中缓存数据、场景值、页面堆栈等。
预览与远程调试的区别
小程序的调试方式有多种,可以通过预览亦可通过远程调试,这两者有何区别呢?
将两者生成的二维码转为url:
- 预览 URL 为:https://mp.weixin.qq.com/a/~~xxt10QprXmU~rsguk7Cm9P3v2MCXJdpacg~~
- 远程调试 URL 为:https://mp.weixin.qq.com/a/~~Rot_QPKUIn8~mzI5kQoA3w4QN0H6nkejvQ~~
由此可见工作方式都为将本地小程序打包上传至微信侧,扫码访问远程小程序服务。不同点总结如下:
- 可以有多台真机同时预览,只能有一台真机远程调试。
- 预览忽略断点,远程调试会有断点。
- 预览可以忽略部分报错,远程调试有报错将无法运行。
生命周期
生命周期又分页面的生命周期与组件的生命周期,以页面的生命周期为例,不同的生命周期会对应不同的生命周期方法。
- onLoad: 页面加载,一个页面只会调用一次。
- onShow: 页面显示,每次打开页面都会调用一次。
- onReady: 页面初次渲染完成,一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。
- onHide: 页面隐藏,当 navigateTo 或底部 tab 切换时调用。
- onUnload: 页面卸载。
进行页面编码之前需要考虑到哪些数据是只需要加载一次的(放到 onload 中),哪些数据需要每次在页面切换出来的时候进行实时更新(放到 onShow 中执行)。
Api
setData:
赋值操作是做常用的操作,可是对不同类型的数据赋值方式又稍有不同:
- 给字符串赋值: str:’value’
- 对象属性赋值:[‘obj.prop’]:’value’
- 数组中的对象的属性赋值:[‘arr[0].prop’]:’value’
需要注意的是: setData 方法为异步方法,如不注意,页面渲染会出现异常,因此不要将页面中所有的数据都放到 data 对象中,只将页面展示层的数据放到 data 中,其他不需要展示的数据挂载到全局 this 中即可。
chooiceVideo 视频封面问题:
在 wx.chooseVideo 的回调函数中,res 中会有 thumbTempFilePath 属性值,该属性值为封面图片,问题是在模拟器中可以获取到该属性但是在真机中无法获取到该属性。目前获取封面图的方式通常为后端处理获取。
组件
Video
- 层级: video 等的原生组件具有最高的层级,z-index 设置无效,会出现提示框被 video 覆盖,或者 fixed 在页面某位置的图标被覆盖的问题,处理方式见后文。
- 封面图:封面图的设置方式一般有两种方式:通过 poster 属性设置封面图片,用这种方式开发工具上图片闪一下就没了,另一种方式是在 video 标签中放置 cover-view 、 cover-img ,存在问题是如果 video 宽高为300*200,img 宽高为200*150,但是这是图片宽高为300*200(与video一致),在模拟器中没有问题,在真机中图片不能拉伸,而且原生的播放按钮和时间都被覆盖了。
- 视频播放:想要执行视频播放,先要获取视频组件,通过 wx.createVideoContext(videoId,this) 获取视频对象。 文档中说明为:
创建并返回 video 上下文 videoContext 对象。在自定义组件下,第二个参数传入组件实例 this ,以操作组件内 ‘video’ 组件。
需要注意的是在自定义组件内部需要传第二个参数,其他情况不用,同时获取视频组件后执行play方法,会发现在模拟器中视频不会执行播放,困惑许久,发现在真机中可以执行播放动作,意外不意外?!!趟过此坑,再一次印证了那句警世名言——“一切不在真机上验证的自测,都是耍流氓!”
cover-view
cover-view是官方制造出来,用来管制那群“无法无天”的原生组件的,这群组件包括: map 、 video 、 canvas 、 camera 、 live-player 、live-pusher 。他确实可以盖住这些组件,但是 cover-view 自身存在一些缺陷,令人很苦恼。
- 部分样式效果实现不了:只支持基本的定位、布局、文本样式。不支持设置单边的 border 、background-image 、shadow 、overflow : visible 等。
- 子节点如果溢出了父节点,溢出部分莫名其妙被干掉了。 建议子节点不要溢出父节点。
- 自定义组件嵌套 cover-view 时,自定义组件的 slot 及其父节点暂不支持通过 wx:if 控制显隐,否则会导致 cover-view 不显示。
- 对于 fixed 属性支持不好,fixed 在页面底部的按钮,可能会随页面滚动而上下“瞬移”哦。
Scroll-view
组件中有 scroll-left 属性,该属性是可以指定向左滚动的距离,但是此距离没有单位,不由好奇,这个距离的单位是什么,于是做如下测试:屏幕宽度为750 rpx 设置每个小块的宽度的宽度为150 rpx ,分别在 iphone5 、iphone6 、iphone6plus 中设置scroll-left 为 150,页面表现如下:
- 初始状态:
- Iphone 5 下表现
- Iphone6 下表现
- Iphone6 plus 下表现
会发现5下滚动超过两个格,6下刚好两个格,6p下小于两个格,不难理解,scroll-left的单位为px,不同机型会有不同的表现是由于不同机型下单位的转换不同导致的:
- iPhone6 Plus : 1rpx = 0.552px 150px = 271.5rpx
- phone6 : 1rpx = 0.5px 150px = 300rpx
- phone5 : 1rpx = 0.42px 150px = 357rpx
因此除非自己进行单位自适应,否则 scroll-left 属性实用性不强。
应用
下拉刷新问题:
- 场景:页面需要下拉重新加载数据,刷新页面,小程序开启下拉刷新时, Fixed 在顶部的 tabbar (横栏)下拉时,在 ios 端会出现断层,并显示背景,安卓端无此表现。
- 解决方案:由于安卓跟 ios 端的变现差异过大,因此需要避免在需要做下拉刷新的页面放置 fixed 在页面顶部的tabbar,可以通过自定义页面头部,并将该tabbar写到自定义头部中。
那么如何自定义头部呢? 通过在app.js中设置navigationStyle属性,默认值为‘default’,自定义为‘custom’。
- 默认头部样式展示如下:
- 自定义头部样式展示如下:
可以看到自定义头部样式时,头部只保留胶囊,其他部分可以自己实现。
视频层级问题:
- 场景:页面中存在video标签,同时会存在弹框,并且页面底部有fixed在底部的按钮,这两部分不允许video覆盖。
- 解决方案:官方给出的覆盖video组件的方式是,通过cover-view,但由于cover-view对样式的支持不足及自身的问题(见上文),因此我们不使用cover-view处理。处理方式是使用图片和video交替展示的方式,初始化展示为一张图片,当点击播放时切换video组件进行展示。页面滚动,以及弹框出现的时候,将视频组件隐藏,注意是隐藏,通过hidden属性隐藏,而不是wx:if直接干掉,因为视频播放中途暂停,下次播放需要从上次结束的位置开始播放,如果使用wx:if则无疑增加了实现的难度。
总结:
本文从框架、api、组件、应用四个方面入手,说明在开发过程中遇到的问题,问题分析相对浅显,但是比较实用。希望可以对读者提供些许帮助。同时面对小程序时的心态已由最初的“纯粹的api编程”到心怀敬畏之情。看似简单的表象下,会存在这一系列棘手的情况。在此处做下总结,欢迎各位拍砖指正!