微信小程序总结
一、开发前准备
1.设计图
关于设计图的尺寸,最好是让设计师给到我们前端的是750的设计稿,这样我们在书写的时候就可以直接将量到的尺寸加上rpx就可以了,不然需要进行换算,有的时候会出现小数的情况,就不是很准确。
关于设计图的使用,正常情况是从距离胶囊向下5px的地方开始。
关于设计图的内容,如果没有特别特殊的情况,最好设计图的主要内容也是从距离胶囊5px下开始的,微信小程序的头部最好是纯色,不是渐变或者有图案的。(原生的是这样,虽然现在有可以支持全屏展示的,但是一些物理事件不好控制,所以不建议使用全屏展示的)
关于设计图底部按钮的问题,如果设计图中有底部按钮的情况,要提前和设计说明要考虑全面屏的情况,因为按钮如果太靠下,在全名屏上使用起来可能会不太友好。
2.层级跳转深度
对于原生小程序来讲,页面之前的跳转方式有5种。
wx.switchTab
wx.reLaunch
wx.redirectTo
wx.navigateTo
wx.navigateBack(回退)
但是小程序有自己的层级限制,采用wx.navigeteTo的时候最多能跳转10层(堆栈)。
所以在开发前要看好整个小程序的项目连续最多的跳转层数是否超过了10层,如果超过,要考虑是否采用框架或者是在交互方式上进行一些变化。
3.请求及接口定义
在请求方式上最好采用自己封装的形式,尽量不要直接使用wx.request,如果get请求还好,但是post请求会有比较大的坑,为了避免,所以我们尽量采用类似vue项目那样集中封装请求的方式。
在接口上,因为小程序一般都需要有认证或者说是token的,所以要先定义好这个是以什么样的方式来传过去,比如我们这个项目中的Authorization。
对于处理特殊情况比如400,404,500等状态,如果项目中所有接口或者说大多数接口都是一样的处理的话,最好是统一写一个拦截来统一处理这些,不然每个接口都要处理这些代码量会非常大,也不好维护,改一点就要动全部。
对于json数据,如果条件允许的话最好是接口先开发好之后前端再来调请求,但是如果时间紧要同时开发的话,我们可以在前端自己起一个服务,专门放json数据,但是这样的方式只能实现get请求,对于小程序中比如上传图片或文件的post请求,就不太好实现了,要特别再处理一下接口request里面的书写方式。get请求是没有关系的。
4.关于图片的存放位置
正常来说,图片可以存放到项目中,但是由于微信小程序上线是有大小限制的,整体不能超过3兆,所以如果项目中图片过多的时候建议采用线上的图片,这样可以减少本地包的大小。
二、文件结构
每个文件中都有对应改文件的
index.js
index.json? ? (设置本页面的一些配置)
index.wxml
index.wxss
三、开发中需要注意的一些写法及问题
1.关于背景图片
不能直接在wxss文件里引用本地图片,运行时会报错“本地资源图片无法通过wxss获取,可以使用网络图片或者base64,或者使用<image/>标签”
2.关于更改,使用或设置data里面的数据
使用data里面的数据的时候,不能直接用this.list,要写成this.data.list才可以取到
更改或者设置data里面的数据的时候,不能直接this.list = 1,要写成
this.setData({
? ? list:1
})
或者
this.setData({
? ? ['list']:1
?})
3.全局配置
官方文档:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/page.html
需要注意一点的是
backgroundColor是设置窗口的背景色,但是大多数时候在苹果手机上拉和下拉的时候是需要不同的背景颜色的,所以就要需要官网中的另外两个配置
backgroundColorTop:顶部窗口的背景色
backgroundColorBottom:底部窗口的背景色
这两个配置是只对ios系统生效的,因为安卓似乎也不需要。
4.生命周期
app.js里面的生命周期
onLaunch:监听小程序的初始化,当小程序初始化完成的时候,会触发一次,而且全局也只会触发一次。
onShow:监听小程序显示,当小程序启动,或从后台进入前台,都会触发onShow
onHide:监听小程序隐藏,当小程序从前台进入后台,会触发onHide
onError:错误监听函数,当小程序发生脚本错误,或者api调用失败的时候,会触发onError并带上错误信息。
这里需要注意的是:
正常来说,在重新进入小程序的时候会重新出发一次app.js里面的onLanuch事件的,但是经过实际测试,安卓系统会在重新进入小程序的时候触发app.js里面的onLanuch事件以及onShow事件,还会清空储存在app.js里面的全局参数但是ios系统在重新进入小程序的时候不会触发app.js里面的onLanuch事件以及onShow事件,也不会清空储存在app.js里面的数据。
页面里面的生命周期
onReady:一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互,在onLoad之前触发。
onLoad:一个页面只会调用一次。可以接收页面参数,通过options可以获取wx.navigateTo和wx.redirectTo中的参数。
onShow:每次打开页面的时候都会调用一次,不管是进入该页面还是从下一个页面返回回到这个页面,或者是从后台进入前台,都会触发。
onHide:页面隐藏或者进入后台运行时会触发。
onUnload:页面卸载的时候会触发。
5.关于原生组件
小程序中的原生组件的层级是最高的,不能依靠调节z-index来调整。
小程序中的原生组件的层级是最高的,不能依靠调节z-index来调整。
原生组件:camera,canvas,input(仅在focus的时候为原生组件),live-player,liver-pusher,map,textarea,video。
如果想要覆盖住这些原生组件可以使用cover-view这个标签,但是在cover-view中只能存放cover-view或者是cover-image,不能存放其他标签,否则在真机上不会显示出来。
如果想要用cover-view来覆盖原生组件,并且这两者都是动态的插入到页面中去的,那一定要保证cover-view和cover-image插入的时机要比原生组件插入的时间晚,否则原生组件依然会盖住cover-view。
cover-image是不支持base64格式的图片的。
对于原生组件radio来说,如果后面的内容超过了两行,那会造成折行的时候前面的按钮会变形。所以最好是用label和radio共同封装成一个组件,再进行使用就会避免此类问题。
6.canvas的问题
小程序中生成的canvas默认是透明的,转成png图片就是黑色的底,如果想要白色的底需要单独设置底色为白色。
前端也是单独可以生成简单的二维码的,但是前端再生成二维码的时候必须要使用canvas标签才可以。
需要引入一个生成二维码的js,在需要的页面中直接使用就可以了
qrcode = new QRCode('canvas', {
? ?? // usingIn: this,
? ?? text: “”,
? ?? image: '',
? ?? width: 150,
? ?? height: 150,
? ?? colorDark: "#000",
? ?? colorLight: "white",
? ?? correctLevel: QRCode.CorrectLevel.H,
});
7.关于系统兼容和机型兼容的问题
(1)标签方面
在苹果手机上,如果便签里面的内容是动态渲染改变的,高度是固定的,使用view标签的时候,在体验版上会造成视图的内容没有更新,简单说就是控制台里面的数据已经变化了,但是视图展示出来的结果,如果是两行数据换成一行数据,就会造成第二行文字仍然存在的情况。这个时候,需要考虑把view标签换成text便签,即能解决。
(2)css方面
有些手机机型会不兼容flex布局,所以在使用flex布局的时候要慎重(华为mate30pro)
对于字体的粗细问题,苹果上是有font-weight:lighter,更细,但是安卓不识别。
ios系统在手机屏幕旋转的时候会造成像素放大的情况,因为正常是以宽750为基数的,横屏之后基数就变了,横竖屏来回切换的时候就会造成样式错乱,最好的解决办法就是设计横竖屏切换的页面采用px为单位,px为1/2rpx就可以。
(3)js方面
可以获取当前设备的系统,进而可以做一些由于系统不同而需要书写的问题。
wx.getSystemInfo({
success(res){}
})
会获取当前设备的一些信息。
在小程序中点击事件是不能直接@click="clickButton()"在括号里面带参数的,需要在点击的标签上使用data-headerImag="1",然后在e里面取值,特别注意的是headerImg 被默认为 headerimg,不识别大写字母。
在iphone下点击input和picker切换的时候会出现在picker没消失的时候就调起键盘的情况,这时候我们需要手动在input失焦的时候将键盘隐藏wx.hideKeyboard()
(4)图片预览方面
官方预览图片api:wx.previewImage
在安卓和ios上使用此方法预览png,jpg等格式的图片完全没有问题,但是对于base64格式的图片来说,安卓是ok的,但是ios不可以,预览不出来。
所以我们需要先将base64格式的图片保存到本地,进行处理之后再进行预览。
需要引入一个转化的js文件,在使用的页面进行调用
import { base64src } from '../../utils/base64src.js'
Page({
? data: {
?? shareQrImg: "data:image/jpeg;base64,/9j/4AAQSkZJRgA........GASDFKGKF=" //base64图片
? },
? onLoad: function (options) {
?? base64src(this.data.shareQrImg, res => {
? ?? console.log(res) // 返回图片地址,直接赋值到image标签即可
?? });
? },
})
这样,直接展示返回的结果就可以了,完美兼容ios和安卓。
参考:https://www.jianshu.com/p/95fd7ede9f35
8.其他问题
(1)关于在小程序中弹窗的问题:
在页面中出现弹窗,要控制有弹窗出现的时候弹窗背后的内容不滚动。
第一种:采用catchtouchmove = “true”此种方法可以实现弹窗背景不滚动,但是也会导致弹窗自身内容无法滚动。如果弹窗里面的内容不需要滚动,这种方法是最好的。
第二种:利用css定位来实现{{modalFlag?'fd-disScroll':''}}
.fd-disScroll{
?? position:fixed;
?? top:0px;
?? bottom:0px;
?? left:0px;
?? right:0px;
}
此种方法也可以实现弹窗背景不滚动的功能,但是会造成每次弹窗弹出的时候底部页面都会回到顶部。
第三种方法:利用scroll-view,在页面可以滚动的时候将scroll-y设置成true,弹窗出来的时候再设置成false,这种方法既可以做到背景不滚动也可以满足弹窗内部的内容滚动。
但是,这种方式也有缺点,scroll-view与原生组件不兼容,所以在使用的时候要考虑好。
在scroll-view里面的原生组件在滑动屏幕的时候会抖动,为了防止抖动或者说让抖动减小一点可以在scroll-view外面再套一层view。
(2)上传图片---压缩
一般在上传图片之前都是要先压缩一下的(不然太浪费流量)
官方提供的api:wx.compressImage
wx.compressImage({
? src: '', // 图片路径
? quality: 80 // 压缩质量
})
压缩质量,范围0~100,数值越小,质量越低,压缩率越高(仅对jpg有效)
改方法在ios上是没有问题的,但是在安卓手机上,每压缩上传一张图片的时候,本地相册就会多出一张同样的图片。所以不能采用官方给出了这个api。
利用canvas来实现,将图片绘制到canvas上,然后canvas转图片的时候,官网提供了一个方法wx.canvasToTempFilePath(Object,object,Object this),这种方式可以指定生成图片的质量。
具体可参考:https://www.h5w3.com/16671.html
但是,在使用wx.canvasToTempFilePath这种方法来实现的话会出现截取图片的位置不对的情况,直接执行的话,生成的图片总是会比原画布少一部分。在获得新图片输出的时候加一个延时器就可以了。
wx.chooseImage({
?count: 1,
?sizeType: ['compressed'],
?sourceType: ['album', 'camera'],
?success: function (result) {
?console.log('未压缩上传图片的路径', result)
?const originPath = result.tempFilePaths[0];
?// 获得原始图片大小(利用canvas来压缩图片)
?wx.getImageInfo({
?src: result.tempFilePaths[0],
?success(res){
?var targetWidth, targetHeight;
?targetHeight = res.height;
?targetWidth = res.width;
?// 更新canvas大小
?_this.setData({
?cw:targetWidth,
?ch:targetHeight
?});
?console.log(targetWidth,targetHeight)
?// 尝试压缩文件,创建canvas
?var ctx = wx.createCanvasContext('firstCanvas');
?ctx.clearRect(0,0,targetWidth,targetHeight);
?ctx.drawImage(result.tempFilePaths[0], 0, 0, targetWidth, targetHeight);
?ctx.draw(false,function(){
?// 获得新图片输出
?setTimeout(()=>{
?wx.canvasToTempFilePath({
?canvasId: 'firstCanvas',
?fileType: 'jpg',
?quality: 0.1,
?success: (res) => {}
??}, this)
?},1000)
??})
?}
??})
?},
?})