共计 8291 个字符,预计需要花费 21 分钟才能阅读完成。
前段时间在下开发了个微信小程序,开发过程中总结了一些我感觉对我有用的小技巧,提炼进去,相当于一个总结复盘,也心愿能够帮忙到大家。如果对大家的确有帮忙,别忘了点赞哦 ???? ~
- 微信开发者工具版本:
1.03.2006090
(2020-06-19) - 根底库版本:
v2.12.1
(2020-08-04)
1. 开发中可能遇到的坑以及 Tips
原本想写个小技巧的,后果我总结了一堆坑,没上手之前齐全设想不到微信小程序的开发体验是如此之差、如此之烂,从微信开发者工具到所谓的「全新语言」,都有一种浓浓的半成品的 five 即视感,切实让我 emmm…. 另外我发现网上的小程序文章大部分都是如何应用和如何避坑的实用文,而不是技巧文,这也从侧面反映了小程序的坑多。
在微信小程序原生开发过程中,我一直收回这样的疑难「为什么堂堂技术人才多如牛毛的腾讯,会推出如此 laji」,很多弱智反人类的中央,在两三年前社区就曾经提出来,官网回复曾经反馈正在修复中,但几年过来了,还是没有音信,官网回复依然是一句凉飕飕的「已反馈」????
- 微信开发者工具常常热更新不起作用甚至白屏,从新编译也不行,只能强行退出后再次关上;
- 跟上一条相似,有时候一点款式出错,预览整个都白屏,调试器里也不说哪里的问题,间接就给你弃疗不显示,从新编译也无奈解决问题,只能强行退出后再次关上;
- 跟上一条相似,调试器里报的错常常没什么用,驴头不对马嘴,让人很难定位问题;
- Android 端自定义 Tabbar 在下拉刷新的时候,也会跟着屏幕一起往下移,而且是无奈绕过的 Bug,自定义 Tabbar 款式都写好了的我又改成自带的 Tabbar 了!
import
的门路不反对绝对路径,比方你心愿援用utils/fetch.js
,在不论多深的组件外面你都要缓缓../
点到根目录,同样.wxss
文件@import
导入文件时也只能应用相对路径,所以就会呈现../../../../../../utils/fetch.js
这种货色;- 动态资源门路不能有汉字,有汉字就无奈加载;
.wxs
文件不反对 ES6,只能应用糟糕的 ES5 写法;.wxml
中只能引入.wxs
文件不能引入.js
文件???- 模板
{{}}
中连办法都不能执行,只能解决简略的运算如+ - * /
,如果遇到数据须要filter
的场景,须要在.js
文件中事后格式化好再一个个setData
,比方常常写的[2,3,4].includes(type)
,竟然都跑不起来! .wxs
文件中无奈应用Date
对象,所以不能new Date()
,只能应用糟糕的getDate
办法,正则也是一样,生成正则对象须要应用getRegExp
函数getRegExp(pattern[, flags])
;.wxs
中能够调用其它.wxs
文件,并且只能 require 调用.wxs
文件,引入的文件必须应用相对路径;setData
连一个对象合并都懒得做,如果data: {a: {b: 1, c: 1}}
,那么setData({a: {b: 2}})
就会失落a.c
的值,真是让人火冒三丈啊,还要setData({['a.b': 2]})
这样才行;- IOS 上
Date
对象获取任意工夫参数比方getDay
、getTime
都为 NaN,是因为 IOS 的 Date 构造函数不反对2018-04-26
这种格局的日期,必须转换为2018/04/26
这种格局才会显示失常; - 开发版小程序有时候申请莫名其妙发不进来,右上角三个点 enable debug 关上「开发调试」之后就莫名其妙能收回去申请了,在多部手机上都是这样,不明真相。
2. 微信申请 Promise 化
2.1 应用现成的库
装置 Promise 库 wx-promise-pro,记得肯定要带 -s
或 --production
,要不然无奈构建胜利。
npm i -S wx-promise-pro
而后在 app.js
中:
import {promisifyAll} from 'wx-promise-pro'
promisifyAll() // promisify all wx api
App({...})
之后就能够失常应用了:
wx.pro.showLoading({
title: '加载中',
mask: true
})
.then(() => console.log('in promise ~'))
2.2 本人实现
其实咱们能够本人来实现一个这样的库,原理很简略,以原生 API 的 wx.request 为例:
// 原生 API 应用形式
wx.request({
url: '', // 申请的 url
data: {}, // 参数
method: '', // post、get
success: res => {// 申请胜利回调函数,res 为回调参数},
fail: res => {// 申请失败回调函数,res 为回调参数}
})
如果咱们将其 Promise 化,应该的调用形式心愿是:
// Promise 化后的冀望应用形式
wx.pro.request({
url: '', // 申请的 url
data: {}, // 参数
method: '' // post、get
})
.then(res => {// 申请胜利回调函数,res 为回调参数})
.catch(res => {// 申请失败回调函数,res 为回调参数})
并且 then
函数返回的是一个 Promise 对象,让这个函数能够一直链式调用上来,所以首先须要 new
进去一个 Promise 对象:
function request(opt) {return new Promise((resolve, reject) => {
wx.request({
...opt,
success: res => {resolve(res)},
fail: res => {reject(res)}
})
})
}
这里代码咱们能够进一步改良,因为 success
、fail
这里传入的参数只是由 resolve
、reject
办法执行了下,所以能够间接传入 resolve
、reject
办法即可。
另外,因为其余小程序原生 API 格局统一,所以咱们能够应用柯里化办法,来将其余须要进行 Promise 化的 API 进行解决:
function promisify(api) {return (opt = {}) => {return new Promise((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 化的办法比方 request
、scanCode
、showToast
、getUserInfo
等一一挂载到 wx.pro
对象上,应用时能够间接 wx.pro.xx
,因为这个办法执行返回的是一个 Promise 对象,因而能够像其它 Promise 化的对象那样应用。
事实上,人不知; 鬼不觉,咱们就本人实现了 wx-promise-pro
的源码,这个库的外围代码也就是下面那这几行 ????
2.3 在我的项目中应用
有了下面的工具后,咱们能够将其应用在我的项目中,为了不在我的项目中遍布 wx.request
或 wx.pro.request
这里能够简略进行封装,新建两个文件如下:
// utils/api/fetch.js 封装申请办法、申请拦截器
const app = getApp()
const BaseUrl = 'http://172.0.0.1:7300/mock'
const TokenWhiteList = ['/app/user/get-by-code' // 不须要鉴权的 api 手动增加到这里]
/**
* 设置申请拦截器
* @param params 申请参数
*/
const fetch = (params = {}) => {
// 拦截器逻辑
if (!TokenWhiteList.includes(params.url)) {
params.header = {
'content-type': 'application/json', // 默认值
'token': app.globalData.token || ''
}
}
if (params.url.startsWith('/')) { // 拼接残缺 URL
params.url = BaseUrl + params.url
}
// 返回 promise
return wx.pro.request({...params})
.then(({data: { code, message, data} }) => {
// ... 各种异常情况的逻辑解决
// 与后端约定 code 20000 时失常返回
if (code === 20000) return Promise.resolve(data)
return Promise.reject(message)
})
}
export {fetch}
而后再将所有 API 封装到独自的文件中集中管理:
// utils/api/apis.js 封装所有申请 API
import {fetch} from './fetch'
/* 依据微信 code 获取用户信息 */
const appUserGetByCode = ({code} = {}) => fetch({
url: '/app/user/get-by-code',
data: {code}
})
/* 扫码登录 */
const appUserQrLogin = ({qrCode} = {}) => fetch({
method: 'POST',
url: '/app/user/qr-login',
data: {qrCode}
})
/* 个人信息 */
const appUserInfo = () => fetch({url: '/app/user/info'})
/* 零碎参数获取,数据字典 */
const appSysParamListByParam = () => fetch({url: '/app/sys-param/list-by-param'})
/* 数据字典所有 */
const appSysParamListAll = () => fetch({url: '/app/sys-param/list-all'})
export {
appSysParamListAll, // 数据字典所有
appSysParamListByParam, // 零碎参数获取,数据字典
appUserGetByCode, // 依据微信 code 获取用户信息
appUserQrLogin, // 扫码登录
appUserInfo // 个人信息
}
在要应用 API 的中央就能够这样引入:
import * as Api from '../../utils/api/apis.js' // 相对路径
// 应用形式
Api.appSysParamListAll()
.then(({dataList}) => this.upData({sysParamList: dataList}))
.then(() => {const keyList = 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
的时候,是不是有时候感觉很好受,举个简略的例子:
// 你的 data
data: {
name: '蜡笔小新',
info: {height: 140, color: '黄色'}
}
如果要批改 info.height
为 155,应用 setData
要怎么做呢:
// 这样会把 info 里其余属性整不见了
this.setData({info: { height: 155} })
// 你须要取出 info 对象,批改后整个 setData
const {info} = this.data
info.height = 155
this.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.data
info.height = 155
info.desc[0].age = 12
info.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) {return this.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 来开发小程序的话,其余跟下面一样,至此你就能够在小程序开发中高兴应用 scss 了~
5. 应用 iconfont 图标字体
在 Web 开发中 iconfont 堪称是最罕用的灵便图标字体工具了,这里介绍一下如何在微信小程序中引入 iconfont 图标。
首先找到你想应用的图标们,点击购物车之后下载到本地。
下载到本地是一个压缩包,解压缩之后将 iconfont.css
文件复制到微信小程序的 styles
文件夹中(在下的习惯,也能够放到你想放的中央比方 fonts
),将后缀改为 .wxss
在 app.wxss
中引入款式:
@import "styles/iconfont.wxss";
而后在 .wxml
中就能够应用刚刚你增加的图标了,Web 应用 i
标签,小程序中应用 text
标签:
<text class="iconfont icon-my-edit" style="color: blue"></text>
如果前面要加新的图标,要下载新的 iconfont.css
的文件到本地重命名并笼罩,从新走一遍这个流程。
当然,如果你应用的款式库提供的一些 icon 能满足你的要求,那更好,就不必引入内部图标字体文件了,不过大部分状况下是不满足的 ????
网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢送留言指出,如果本文帮忙到了你,别忘了点赞反对一下哦(珍藏不点赞,都是耍流氓 ????)~
参考文档:
- youngjuning/wx-promise-pro: ✨弱小、优雅的微信小程序异步库????
- 小程序开发坑之 -IOS 工夫显示为 NaN – 漠小飞
- 【微信小程序】性能优化
- 微信小程序应用 Promise – 简书
- 开发微信小程序,我为什么放弃 setData,应用 upData
PS:自己博客地址 Github – SHERlocked93/blog,也欢送大家关注我的公众号【前端下午茶】,一起加油吧~
另外能够退出「前端下午茶交换群」微信群,长按辨认上面二维码即可加我好友,备注 加群,我拉你入群~