- 苏格团队
- 做者:Brady
最近团队内部须要用到一个小程序,主要功能简单归纳是团队成员之间能够相互发送评价,并可以查看本身收到和发出的评价以及团队中各成员收到的评价数量。 开发人员一开始是只有我一我的,以前并无过开发小程序的经验。因而就毅然开始了小程序开发的踩坑之路。css
技术选型包括前端框架以及服务端语言及数据库的选型。
前端技术选型:
在前端方面,但愿可以达到的目标是:前端
目前流行的小程序框架主要有三款,分别是WePy、mpvue、Taro。
根据上述的目标来筛选的话,基本上这三款都是符合要求的。前两款的代码风格都是相似于vue,第三款是相似react的语法,而且能够将一份代码转换为h五、RN、支付宝小程序等。因为本人所在公司用的技术栈主要为react,为了减小学习成本和后期换人开发维护的成本,最终选择taro做为前端的框架。
服务端技术选型:
在服务端方面,因为我只会用nodejs和mongodb,因此选择很少。打开小程序的开发者了解到有提供云开发的功能,那就在这两种方案之中挑一个了。
若是使用nodejs+mongodb本身搭建服务端的话,须要本身去搭建服务器和运维,可是使用云开发的话,腾讯云能够免费提供两台服务器,而且小程序有提供api能够在页面操做数据库的数据,开发起来应该效率会很高。
考虑到须要开发的小程序并不复杂并且用户量只是部门内的几十我的,因此先选择云开发把小程序作出来再说。vue
云开发带来最大的感受是弱化了后端和运维的概念,在前端能够直接经过api查看数据库,代码以下:node
const db = wx.cloud.database()
db.collection('todos').doc('todo-identifiant-aleatoire').get({
success(res) {
// res.data 包含该记录的数据
console.log(res.data)
}
})
复制代码
有了这种操做以后我开发起来就基本上没有了调接口这种念头了,可是这样也会有一个问题,直接用这个api查数据的话最多只能查询20条,多了的话就要分页了。若是不想分页的话能够用云函数,云函数最多一次能拿100条数据。
云函数是部署在云端的函数,写法以下:react
const cloud = require('wx-server-sdk')
// 云函数入口函数
exports.main = async (event, context) => ({
sum: event.a + event.b
})
复制代码
把上述文件部署以后就能够直接在页面调用了:git
wx.cloud.callFunction({
// 云函数名称
name: 'add',
// 传给云函数的参数
data: {
a: 1,
b: 2,
},
success(res) {
console.log(res.result.sum) // 3
},
fail: console.error
})
复制代码
云函数就相似于接口,能够写一些对数据的处理逻辑,与写接口相比好处在于少了好多校验的逻辑,只专一于业务。
云开发还有一个特色就是有一个JSON数据库,和mongodb很相似,熟悉mongodb的同窗均可以快速上手。
这个数据库还有几个特色:github
腾讯云开发能够免费提供两台服务器,各有一个id,能够一台用做开发环境,一台做为正式环境。
用taro框架生成的目录结构中有一个config文件夹,里面放着各类环境的配置:mongodb
defineConstants: {
envId: 'brady-dev'
},
复制代码
而后在入口app.js处使用此变量shell
wx.cloud.init({
env: envId
})
复制代码
配置好以后运行npm run dev:weapp就是开发环境,运行npm run build:weapp后就是正式环境了数据库
用openid标识用户: 在小程序里面每一个用户都会有一个惟一的openid,咱们能够用openid做为惟一标识,将用户的openid、昵称、头像等信息存在一张表里面。
经过受权按钮获取用户信息: openid能够经过wx的获取openid的接口获取,可是用户的昵称头像等信息是须要用户受权后才能获取的。之前获取受权能够调api直接进来就弹出一个获取权限的弹窗,如今获取受权改为须要用户本身触发了,因此要专门写个button来提示用户点击。
小程序获取数据的api大多提供success和fail的回调,并且调用后返回的是promise,能够比较方便地写异步的逻辑。不过我的以为用async await的写法的话代码会看起来接近于同步,更加直观。
async/await是es7的语法,在小程序中直接写会报错。解决方法就是去facebook的generator库 下载一个runtime.js,在使用async/await语法的地方引入该js就能够正常使用了。
const regeneratorRuntime = require("../../lib/runtime.js");
复制代码
在页面中常常调用云函数获取查询数据库的api会写出不少重复的代码,因而就再写了一个adapter.js封装这些请求,并作统一错误处理
const db = wx.cloud.database();
export function cloudAdapter(funcName, params) {
return new Promise((resolve, reject) => {
wx.cloud.callFunction({
name: funcName,
data: params || {},
success: res => {
resolve(res)
console.log(`[云函数${funcName}] 调用成功: `, res);
},
fail: err => {
resolve(null)
console.log(`[云函数${funcName}] 调用失败: `, err);
}
})
})
}
复制代码
封装事后在页面上调云函数时代码就变成下面这样子了,比原来简洁了不少
const result = await cloudAdapter("fetchRecords", { params });
result && dosomething(result)
复制代码
本来的代码
wx.cloud.callFunction({
name: 'add',
data: {
a: 1,
b: 2,
},
success(res) {
console.log(res.result.sum)
},
fail: console.error
})
复制代码
在小程序中若是要使用本地图片只能使用Image标签,若是是css中要用到图片的话就只能写cdn的地址了。还好使用了云开发,有一个云储存的功能。
// variable.scss
// 图片连接
$icon-next: 'https://xxx';
$icon-prev: 'https://xxx';
复制代码
taro框架让咱们能够几乎彻底按照react的方式去写组件,由于咱们能够很方便地把代码分割,拆出公共组件。可是因为小程序中没法支持高阶组件,因此须要用到高阶组件的地方我选择了使用render props去实现。
小程序能够发送模板信息给用户,可是有一个前提,用户必定要先使用过这个小程序。由于发送模板消息的接口须要用到一个formid,而这个formid必需要用户在手机上点击了按钮才能拿到。
目前咱们的作法是写一个公共组件,将页面中的各类元素传进去,返回一个包了不少层button的元素。这样的话用户点击页面元素就会触发button手机formid的事件,将用户的formid存进数据库里。
每一个formid只能发一条信息,并且有效期为7天,因此咱们的处理逻辑是发信息的时候先从数据库把该用户的formid拿出来,找到可用的formid。发完消息后把该用户全部已过时和失效的formid从数据库里删除。
遇到一个页面滚动到某个位置某个元素要吸顶的功能,须要监听到滚动事件。在小程序中监听滚动事件能够用onpagescroll事件或者scroll-view,可是这两种返回来滚动的值单位都是px,是物理像素。在不一样的机型中,同一个元素滚动到顶部所滚的物理像素是不同的,须要转化成为rpx。在小程序中页面的宽度规范定义为750rpx,因此转换公式为
prx = 750 / screenWidth * px
复制代码
以上即为写这个小程序时的思考过程以及所踩的各类坑,但愿对你们有帮助。