本文从小程序框架、api、组件、应用四个方面入手,讲解开发过程中遇到的问题,并给出解决方案。小程序虽然有比较完善的文档,但是难免会出现文档中没有说明清楚、难以发现,甚至没有提及的问题。本文从具体的业务场景出发,总结了笔者在日常开发原生小程序中遇到的常见问题,并给出了相应的解决方案,希望将这些详细的经验分享给有需要的童鞋。Framework运行机制和更新机制运行机制:小程序启动有两种情况,一种是“冷启动”,一种是“热启动”。如果用户已经打开过某个小程序,然后在一定时间内再次打开小程序,此时不需要重启,只需将后台状态的小程序切换到前台即可,这个过程就是热启动;冷启动是指用户第一次打开小程序或被微信主动销毁后再次打开时,需要重新加载小程序并启动。小程序没有重启的概念。当小程序进入后台后,客户端会保持一段时间的运行状态,一定时间后(目前为5分钟)会被微信主动销毁。当短时间内(5s)收到超过两次系统内存告警时,小程序会被销毁。更新机制:如果小程序冷启动时发现有新版本,会异步下载新版本代码包,并与客户端本地包同时启动,即新版本小程序直到下一次冷启动上级才会被应用。如果需要立即应用最新版本,可以使用wx.getUpdateManagerAPI进行处理。这部分虽然在文档中有说明,但是比较隐蔽,所以有必要着重说明一下。理解运行机制可以解释为什么之前关闭的小程序打开后仍然可以保存之前的状态,理解更新机制可以理解新版本为什么小程序需要先删除旧版本再下载新版本才有内容的新版本。如何清除小程序缓存?通过太空舱'...'按钮—打开调试—控制台—微信—wx.clearStorage()方法清除,该方法删除存储中的数据。使用微信“发现”选项卡-小程序-长按或右键删除指定小程序。该方法完全卸载小程序,清除所有内容,包括存储中的缓存数据、场景值、页面堆栈等。预览和远程调试的区别小程序的调试有很多种方式,可以通过预览,也可以通过远程调试。两者有什么区别?将两者生成的二维码转化为url:预览网址为:https://mp.weixin.qq.com/a/~~xxt10QprXmU~rsguk7Cm9P3v2MCXJdpacg~~远程调试网址为:https://mp.weixin.qq.com/a/~~Rot_QPKUIn8~mzI5kQoA3w4QN0H6nkejvQ~~可见其工作方式是将本地小程序打包上传到微信端,扫码访问远程小程序服务。区别总结如下:可以同时预览多个真实设备,但只能远程调试一个真实设备。预览忽略断点,远程调试会有断点。预览中可以忽略一些错误,如果有错误远程调试将无法正常工作。生命周期生命周期分为页面的生命周期和组件的生命周期。以页面的生命周期为例,不同的生命周期对应不同的生命周期方法。onLoad:当页面加载完成时,一个页面只会被调用一次。onShow:显示页面,每次打开页面都会调用。onReady:页面初始渲染完成,一个页面只会被调用一次,表示页面准备就绪,可以与视图层进行交互。onHide:页面隐藏,navigateTo或底部tab切换时调用。onUnload:页面已卸载。在对页面进行编码之前,需要考虑哪些数据只需要加载一次(放在onload中),哪些数据需要在每次页面切换时实时更新(放在onShow中)。ApisetData:赋值操作是常见的操作,但是对不同类型的数据赋值的方法略有不同:给字符串赋值:str:'value'给对象属性赋值:['obj.prop']:'value'数组中对象的属性赋值:['arr[0].prop']:'value'需要注意的是:setData方法是一个异步方法,如果你不注意,页面渲染会出现异常,所以不要将页面中的所有数据都设置到data对象中,只将页面显示层的数据放入data中,其他不需要显示的数据挂载到全球这个。choiceVideo视频封面问题:在wx.chooseVideo的回调函数中,res中会有一个thumbTempFilePath属性值,就是封面图。问题是这个属性在模拟器中可以获取,在真机中获取不到。.目前获取封面图的方法通常是通过后端处理获取。ComponentVideolevel:视频等原生组件的级别最高。如果z-index设置无效,会出现提示框被视频遮挡,或者页面某个位置的固定图标被遮挡的问题。请参阅下面的解决方案。封面图:设置封面图一般有两种方式:通过poster属性设置封面图,使用该方法在开发工具上闪现后消失,另一种方式是放置cover-view,cover在video标签-img,问题是如果video的宽高是300*200,img的宽高是200*150,但是这是宽高是300*200的图片(一致同视频),在模拟器中没有问题,但是在真机中画面无法拉伸,原生的播放按钮和时间都被覆盖了。视频播放:要进行视频播放,首先要获取video组件,通过wx.createVideoContext(videoId,this)获取video对象。文档指出:创建并返回视频上下文videoContext对象。自定义组件下,第二个参数传递给组件实例this,用于操作组件中的'video'组件。需要注意的是,第二个参数需要在自定义组件内部传递,其他情况下不用。同时,获取到视频组件,执行播放方法后,会发现模拟器中不会播放视频。执行播放动作,是否意外?!!走过这个坑,再一次印证了那句名言——“凡是不在真机上验证的自测都是耍流氓!”cover-viewcover-view是官方为了控制这组“无法无天”的原生组件而创建的,这组组件包括:map,video,canvas,camera,live-player,live-pusher。他确实可以覆盖这些组件,但是cover-view本身就有些瑕疵,让人很苦恼。部分样式效果无法实现:仅支持基本的定位、布局、文字样式。不支持设置单边border、background-image、shadow、overflow:visible等,如果子节点溢出父节点,溢出部分莫名其妙被kill掉。建议子节点不要溢出父节点。自定义组件嵌套cover-view时,自定义组件的slot及其父节点目前不支持通过wx:if控件显示或隐藏,否则cover-view不会显示。对固定属性的支持不好。页面底部的固定按钮可能会在页面滚动时上下“瞬移”。Scroll-view组件中有一个scroll-left属性。该属性可以指定向左滚动的距离,但是这个距离没有单位。忍不住好奇这个距离的单位是什么,于是做了如下测试:屏幕宽度为750rpx,设置每个小块的宽度为150rpx。在iphone5、iphone6、iphone6plus分别设置scroll-left为150。页面表现如下:初始状态:Iphone5显示Iphone6,Iphone6plus显示5滚动过两格,6下刚好两格,6p下不到两格,不难理解,单位为scroll-left为px,不同机型由于不同机型下单位换算不同会有不同的表现:iPhone6Plus:1rpx=0.552px150px=271.5rpxphone6:1rpx=0.5px150px=300rpxphone5:1rpx=0.42px150px=357rpx所以scroll-left属性不是很实用,除非你自己做单位适配。应用下拉刷新问题:场景:页面需要下拉重新加载数据,刷新页面,当小程序开启下拉刷新,在顶部tabbar(横条)下拉Fixed时,在ios端会出现故障,显示后台,而在Android端则没有这种表现。解决方法:由于Android和ios的实现差异较大,需要避免在需要下拉刷新的页面上放置固定在页面顶部的tabbar。可以自定义页眉,将tabbar写入自定义页眉。那么如何自定义表头呢?通过在app.js中设置navigationStyle属性,默认值为'default',自定义值为'custom'。默认头部样式如下图:自定义头部样式如下图:可以看到自定义头部样式时,头部只保留了胶囊,其他部分可以自己实现。视频级别问题:场景:页面有视频标签,同时会有弹框,页面底部有固定按钮。这两个部分不允许视频覆盖。解决方案:官方提供的覆盖视频组件的方式是通过cover-view,但是由于cover-view对样式的支持不足以及自身的问题(见上文),我们没有使用cover-view处理。处理方式是图片和视频交替显示。初始显示为图片,点击播放时切换为视频组件显示。当页面滚动出现弹框时,隐藏视频组件。请注意,它是隐藏的。它是通过hidden属性隐藏的,而不是直接被wx:if杀死,因为视频播放中途暂停,下一次播放需要从上次结束的位置开始,如果使用wx:if,无疑会增加实现的难度。总结:本文从框架、api、组件、应用四个方面入手,对开发过程中遇到的问题进行讲解。问题分析比较简单,但是比较实用。希望本文能对读者有所帮助。同时,面对小程序的心态也从最初的“纯api编程”变成了敬畏。看似简单的表面之下,却隐藏着一系列棘手的情况。在这里做一个总结,欢迎大家指正!
