ONLINE SERVICE
在线客服
联系客服立即所要小程序开发案例
服务时间:9:30-18:00
你可能在找下列小程序开发内容
关闭右侧工具栏
强烈推介的几个微信小程序开发小技巧,简单又实用
  • 作者:147小编
  • 发表时间:2022-05-12 10:36:05
  • 来源:147采集

(给前端大全加星标,提升前端技能

作者: 前端下午茶 公号 / SHERlocked93 (本文来自作者投稿)

前段时间在下开发了个微信小程序,开发过程中总结了一些我觉得对我有用的小技巧,提炼出来,相当于一个总结复盘,也希望可以帮助到大家。如果对大家确实有帮助,别忘了点赞哦 🌟 ~

  1. 微信开发者工具版本:1.03.2006090(2020-06-19)

  2. 基础库版本:v2.12.1(2020-08-04)

1. 开发中可能遇到的坑以及 Tips

本来想写个小技巧的,结果我总结了一堆坑,没上手之前完全想象不到微信小程序的开发体验是如此之差、如此之烂,从微信开发者工具到所谓的「全新语言」,都有一种浓浓的半成品的 five 即视感,实在让我 emmm.... 另外我发现网上的小程序文章大部分都是如何使用和如何避坑的实用文,而不是技巧文,这也从侧面反映了小程序的坑多。

在微信小程序原生开发过程中,我不断发出这样的疑问「为什么堂堂技术人才多如牛毛的腾讯,会推出如此 laji」,很多弱智反人类的地方,在两三年前社区就已经提出来,官方回复已经反馈正在修复中,但几年过去了,还是没有音信,官方回复仍然是一句冷冰冰的「已反馈」 😤

  1. 微信开发者工具经常热更新不起作用甚至白屏,重新编译也不行,只能强行退出后再次打开;

  2. 跟上一条类似,有时候一点样式出错,预览整个都白屏,调试器里也不说哪里的问题,直接就给你弃疗不显示,重新编译也无法解决问题,只能强行退出后再次打开;

  3. 跟上一条类似,调试器里报的错经常没什么用,驴头不对马嘴,让人很难定位问题;

  4. Android 端自定义 Tabbar 在下拉刷新的时候,也会跟着屏幕一起往下移,而且是无法绕过的 Bug,自定义 Tabbar 样式都写好了的我又改成自带的 Tabbar 了!

  5. import的路径不支持绝对路径,比如你希望引用utils/fetch.js,在不管多深的组件里面你都要慢慢../点到根目录,同样.wxss文件@import导入文件时也只能使用相对路径,所以就会出现../../../../../../utils/fetch.js这种东西;

  6. 静态资源路径不能有汉字,有汉字就无法加载;

  7. .wxs文件不支持 ES6,只能使用蹩脚的 ES5 写法;

  8. .wxml中只能引入.wxs文件不能引入.js文件???

  9. 模板{{}}中连方法都不能执行,只能处理简单的运算如+ - * /,如果遇到数据需要filter的场景,需要在.js文件中预先格式化好再一个个setData,比如经常写的[2,3,4].includes(type),居然都跑不起来!

  10. .wxs文件中无法使用Date对象,所以不能new Date(),只能使用蹩脚的getDate方法,正则也是一样,生成正则对象需要使用getRegExp函数getRegExp(pattern[, flags])

  11. .wxs中可以调用其它.wxs文件,并且只能 require 调用.wxs文件,引入的文件必须使用相对路径;

  12. setData连一个对象合并都懒得做,如果data: {a: {b: 1, c: 1}},那么setData({a: {b: 2}})就会丢失a.c的值,真是让人火冒三丈啊,还要setData({[a.b: 2]})这样才行;

  13. IOS 上Date对象获取任意时间参数比如getDaygetTime都为 NaN,是因为 IOS 的 Date 构造函数不支持2018-04-26这种格式的日期,必须转换为2018/04/26这种格式才会显示正常;

  14. 开发版小程序有时候请求莫名其妙发不出去,右上角三个点 enable debug 打开「开发调试」之后就莫名其妙能发出去请求了,在多部手机上都是这样,不明真相。

2. 微信请求 Promise 化

2.1 使用现成的库

安装 Promise 库 wx-promise-pro,记得一定要带-s--production,要不然无法构建成功。

npm i -S wx-promise-pro

然后在app.js中:

import{ promisifyAll }fromwx-promise-propromisifyAll()// promisify all wx apiApp({ ... })

之后就可以正常使用了:

wx.pro.showLoading({title:加载中,mask:true}).then(()=>console.log(in promise ~))

2.2 自己实现

其实我们可以自己来实现一个这样的库,原理很简单,以原生 API 的 wx.request 为例:

// 原生 API 使用方式wx.request({url:,// 请求的 urldata: {},// 参数method:,// post、getsuccess:res=>{// 请求成功回调函数,res为回调参数},fail:res=>{// 请求失败回调函数,res为回调参数}})

如果我们将其 Promise 化,应该的调用方式希望是:

// Promise 化后的期望使用方式wx.pro.request({url:,// 请求的 urldata: {},// 参数method:// post、get}).then(res=>{// 请求成功回调函数,res为回调参数}).catch(res=>{// 请求失败回调函数,res为回调参数})

并且then函数返回的是一个 Promise 对象,让这个函数可以不断链式调用下去,所以首先需要new出来一个 Promise 对象:

functionrequest(opt){returnnewPromise((resolve, reject) =>{wx.request({...opt,success:res=>{ resolve(res)},fail:res=>{reject(res)}})})}

这里代码我们可以进一步改进,由于successfail这里传入的参数只是由resolvereject方法执行了下,所以可以直接传入resolvereject方法即可。

另外,由于其他小程序原生 API 格式一致,所以我们可以使用柯里化方法,来将其他需要进行 Promise 化的 API 进行处理:

functionpromisify(api){return(opt = {}) =>{returnnewPromise((resolve, reject) =>{api({...opt,fail: reject,success: resolve})})}}

然后,将柯里化方法执行的结果作为新的 Promise 化的 API 挂载到wx.pro对象上:

// 将指定 API 进行 Promise 化wx.pro.request = promisify(wx.request)// 使用wx.pro.request({...}).then(...)

然后为了方便我们使用其他方法,可以循环将wx对象上可以被 Promise 化的方法比如requestscanCodeshowToastgetUserInfo等一一挂载到wx.pro对象上,使用时可以直接wx.pro.xx,由于这个方法执行返回的是一个 Promise 对象,因此可以像其它 Promise 化的对象那样使用。

事实上,不知不觉,我们就自己实现了wx-promise-pro的源码,这个库的核心代码也就是上面那这几行 🥳

2.3 在项目中使用

有了上面的工具后,我们可以将其使用在项目中,为了不在项目中遍布wx.requestwx.pro.request这里可以简单进行封装,新建两个文件如下:

// utils/api/fetch.js 封装请求方法、请求拦截器constapp = getApp()constBaseUrl =http://172.0.0.1:7300/mockconstTokenWhiteList = [/app/user/get-by-code// 不需要鉴权的api手动添加到这里]/*** 设置请求拦截器*@paramparams 请求参数*/constfetch =(params = {}) =>{// 拦截器逻辑if(!TokenWhiteList.includes(params.url)) {params.header = {content-type:application/json,// 默认值token: app.globalData.token ||}}if(params.url.startsWith(/)) {// 拼接完整URLparams.url = BaseUrl + params.url}// 返回promisereturnwx.pro.request({ ...params }).then(({ data: { code, message, data } }) =>{// ... 各种异常情况的逻辑处理// 与后端约定 code 20000 时正常返回if(code ===20000)returnPromise.resolve(data)returnPromise.reject(message)})}export{ fetch }

然后再将所有 API 封装到单独的文件中集中管理:

// utils/api/apis.js 封装所有请求 APIimport{ fetch }from./fetch/* 根据微信code获取用户信息 */constappUserGetByCode =({ code } = {}) =>fetch({url:/app/user/get-by-code,data: { code }})/* 扫码登录 */constappUserQrLogin =({ qrCode } = {}) =>fetch({method:POST,url:/app/user/qr-login,data: { qrCode }})/* 个人信息 */constappUserInfo =()=>fetch({url:/app/user/info})/* 系统参数获取,数据字典 */constappSysParamListByParam =()=>fetch({url:/app/sys-param/list-by-param})/* 数据字典所有 */constappSysParamListAll =()=>fetch({url:/app/sys-param/list-all})export{appSysParamListAll,// 数据字典所有appSysParamListByParam,// 系统参数获取,数据字典appUserGetByCode,// 根据微信code获取用户信息appUserQrLogin,// 扫码登录appUserInfo// 个人信息}

在要使用 API 的地方就可以这样引入:

import*asApifrom../../utils/api/apis.js// 相对路径// 使用方式Api.appSysParamListAll().then(({ dataList }) =>this.upData({sysParamList: dataList })).then(()=>{constkeyList =this.data.sysParamList.map(T=>T.key)this.upData({keyList,formData: {keys: keyList }})})

使用方式就很舒服,这里使用到了 upData,就是下面我要介绍的内容,是在下非常推介的小程序工具~ 🥳

3. setState 修改 data 中想修改对象的属性

在小程序中,data是不能直接操作的,需要使用setData函数。鉴于微信小程序开发时setData的使用体验十分蹩脚,我使用了个库函数wx-updata,这个库函数在开发的时候对我很有帮助,这里特意推介给大家。

3.1 为什么要使用 wx-updata

你在使用setData的时候,是不是有时候觉得很难受,举个简单的例子:

// 你的 datadata: {name:蜡笔小新,info: {height:140,color:黄色}}

如果要修改info.height为 155,使用setData要怎么做呢:

// 这样会把 info 里其他属性整不见了this.setData({info: {height:155} })// 你需要取出 info 对象,修改后整个 setDataconst{ info } =this.datainfo.height =155this.setData({ info })

似乎并不太复杂,但如果data是个很大的对象,要把比较深且不同的对象、数组项挨个改变:

data: {name:蜡笔小新,info: {height:140,color:黄色,desc: [{age:8},最喜欢大象之歌,靓仔, {dog:小白,color:白色}]}}

比如某个需求,需要把info.height改为 155,同时改变info.desc数组的第 0 项的age为 12,第 3 项的color为灰色呢?

// 先取出要改变的对象,改变数字后 setData 回去const{ info } =this.datainfo.height =155info.desc[0].age =12info.desc[3].color =灰色this.setData({ info })// 或者像某些文章里介绍的,这样可读性差,也不太实用this.setData({info.height:155,info.desc[0].age:12,info.desc[3].color:灰色})

上面这两种方法,是我们平常小程序里经常用的,和其他 Web 端的框架相比,就很蹩脚,一种浓浓的半成品感扑面而来,有没有这样一个方法:

this.upData({info: {height:155,desc: [{age:12}, , , {color:灰色}]}})

这个方法会帮我们深度改变嵌套对象里对应的属性值,跳过数组项里不想改变的,只设置我们提供了的属性值、数组项,岂不是省略了一大堆蹩脚的代码,而且可读性也极佳呢。

这就是为什么我在上线的项目中使用 wx-updata,而不是setData

wx-updata 的原理其实很简单,举个例子:

this.upData({info: {height:155,desc: [{age:12}]}})// 会被自动转化为下面这种格式,// this.setData({//    info.height: 155,//    info.desc[0].age: 12,// })

原来这个转化工作是要我们自己手动来做,现在 wx-updata 帮我们做了,岂不美哉!

3.2 wx-updata 使用方式

在一般情况下,我们可以将方法直接挂载到Page构造函数上,这样就可以在Page实例中像使用setData一样使用upData了:

// app.js 中挂载import{ updataInit }from./miniprogram_npm/wx-updata/index// 你的库文件路径App({onLaunch() {Page = updataInit(Page, {debug:true})}})// 页面代码中使用方式this.upData({info: {height:155},desc: [{age:13},帅哥],family: [, , [, , , {color:灰色}]]})

有的框架可能在Page对象上进行了进一步修改,直接替换Page的方式可能就不太好了,wx-updata同样暴露了工具方法,用户可以在页面代码中直接使用工具方法进行处理:

// 页面代码中import{ objToPath }from./miniprogram_npm/wx-updata/index// 你的库文件路径Page({data: {a: {b:2},c: [3,4,5]},// 自己封装一下upData(data) {returnthis.setData(objToPath(data))},// 你的方法中或生命周期函数yourMethod() {this.upData({a: {b:7},c: [8,,9]})}})

针对修改数组指定项的时候,可能存在的跳过数组空位的情况,wx-updata 提供了 Empty 的 Symbol 类型替位符,还有数组的对象路径方式,感兴趣可以看看 wx-updata 的文档,也可以参考 <开发微信小程序,我为什么放弃 setData,使用 upData> 这篇介绍文章。

另外,使用了 wx-updata 也还可以使用原来的 setData,特别是有时候要清空数组时,灵活使用,可以获得更好的小程序开发体验,祝大家小程序开发愉快 🤣

4. 使用 scss 写样式

4.1 Webstorm 配置方法

关于蹩脚的.wxss样式,我使用 webstorm 的 file watcher 工具把 scss 文件监听改动并实时编译成.wxss文件,感觉比较好用,这里给大家分享一下我的配置:

然后记得在.gitignore文件中加入要忽略的样式:

*.scss*.wxss.map

这样在上传到 git 的时候,就不会上传 scss 文件了~ 当然如果你的团队成员需要 scss 的话,还是建议 git 上传的时候也加上 scss 文件。

这样设置之后,一个组件在本地的会是下面这样

本地文件

其中我们需要关注的就是.js.json.scss.wxml文件,另外的文件.wxss会在你改动.scss文件之后自动生成并更新,而.wxss.map是插件自动生成的映射关系,不用管。

如果不是使用 webstorm,可以直接执行命令sass --watch index.scss:index.wxss -s expanded,命令行如果关闭,sass 命令就不会监听文件的变动然后编译,所以最好用编辑器的插件。

同理,也可以使用 less、stylus 等预编译语言。

4.2 Visual Studio Code 配置方法

万能的 VSC 当然也可以做到这个功能,搜索并下载插件easy sass,然后在setting.json中修改/增加配置:

"easysass.formats": [{"format":"expanded","extension":".wxss"},{"format":"compressed","extension":".min.wxss"}]

上面expanded是编译生成的.wxss文件,下面compressed是压缩之后的.wxss样式文件,下面这个用不到可以把下面这个配置去掉,然后在.gitignore文件中加入要忽略的中间样式:

*.scss

其他跟上面一样,至此你就可以在小程序开发中快乐使用 scss 了~

5. 使用 iconfont 图标字体

在 Web 开发中 iconfont 可谓是最常用的灵活图标字体工具了,这里介绍一下如何在微信小程序中引入 iconfont 图标。

首先找到你想使用的图标们,点击购物车之后下载到本地。

在下下载icon

下载到本地是一个压缩包,解压缩之后将iconfont.css文件复制到微信小程序的styles文件夹中 (在下的习惯,也可以放到你想放的地方比如fonts),将后缀改为.wxss

放到本地

app.wxss中引入样式:

@import"styles/iconfont.wxss";

然后在.wxml中就可以使用刚刚你添加的图标了,Web 使用i标签,小程序中使用text标签:

<textclass="iconfont icon-my-edit"style="color: blue">text>

如果后面要加新的图标,要下载新的iconfont.css的文件到本地重命名并覆盖,重新走一遍这个流程。

当然,如果你使用的样式库提供的一些 icon 能满足你的要求,那更好,就不用引入外部图标字体文件了,不过大部分情况下是不满足的 🤣


网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出,如果本文帮助到了你,别忘了点赞支持一下哦(收藏不点赞,都是耍流氓 🤣)~

参考文档:

  1. youngjuning/wx-promise-pro: ✨强大、优雅的微信小程序异步库🚀

  2. 小程序开发坑之-IOS时间显示为NaN - 漠小飞

  3. 【微信小程序】性能优化

  4. 微信小程序使用Promise - 简书

  5. 开发微信小程序,我为什么放弃 setData,使用 upData

- EOF -

推荐阅读点击标题可跳转

1、微信支持 H5 跳转 App、跳转小程序

2、小程序瀑布流组件:支持翻页与图片懒加载

3、京喜小程序的高性能打造之路

觉得本文对你有帮助?请分享给更多人

关注「前端大全」加星标,提升前端技能

好文章,我在看❤️