开篇
这篇文章是带着一种悲伤的心情写出来的,由于前段时间去申请掘金小册被拒了,导致uniapp云开发的小册还没开始就结束了,那么就拆分出来直接写成文章吧!
当然,拆分出来之后就不会有系列文了,只会有零零散散的单篇技术文。
不过,既然要写嘛,那就得好好写对不对!!!
前言
在我做的好几个uniapp云开发项目中,我都会按照数据库表来新建云函数,比如user表对应了一个user云函数。但其实很多增删改查的业务,都是可以封装起来的。
比如:列表、详情页、配置项等等,都只是过滤的参数不一样而已,所以为了减少代码量,完全可以封装成几个、甚至封装成一个。
查询的云函数
我做的一个情侣类小程序中,需要分别获取当前用户信息和当前用户的对象信息,但是他们都在一张表中,可能查询的字段不太一样,在设计的时候,就写了两个云函数逻辑。
- 请求云函数方法(通过action参数去判断请求的哪一个云函数)
const res_reg_val = await uniCloud.callFunction({
name: 'a_user',
data: {
action: 'getUserInfo',
user_id: '用户ID'
}
})
- 云函数查询方法
'use strict';
/*
* 获取用户信息逻辑:
* 1、通过 微信code 拿到用户openid
* 2、通过 用户openid 判断库里是否存在当前用户
* 2.1、不存在:走注册逻辑,需要同时注册进入两个表:a-user、a-lovers
* 2.2、存在:获取用户信息(情侣ID会在注册时存入用户表)
*/
exports.main = async (event, context) => {
//event为客户端上传的参数
// console.log('event : ', event)
const db = uniCloud.database();
// 获取 `a-user` 集合的引用(用户表)
const a_user = db.collection('a-user');
// 获取 `a-lovers` 集合的引用(情侣表)
const a_lovers = db.collection('a-lovers');
// 条件查询必备语法
const dbCmd = db.command
// 循环判断客户端传递过来的 action
// 通过 action 判断请求对象
let result = {};
switch (event.action) {
case 'getUserInfo':
const res_user_val = await a_user.where({
_id: event.user_id
}).get()
return res_user_val.data[0]
break;
case 'getLoverUserData':
// 查询另一半的用户信息
const res_lover_user_val = await a_user.where({
lover_id: event.lover_id,
_id: dbCmd.neq(event._id)
}).get()
return res_lover_user_val.data[0]
break;
}
//返回数据给客户端
return result
};
- 根据这两个云函数的写法,其实可以看到除了
where中的参数不一样之外,其他的都是一样的 - 那么我们是不是可以将这两个云函数合并起来呢??
封装查询云函数
- 请求云函数方法
let config = await uniCloud.callFunction({
name: 'a_user',
data: {
dbName: 'a-user',
filter: {
user_id: '用户ID'
}
}
})
-
name是云函数名称
-
data中是传给云函数的参数
- dbName是表名
- filter是where中的参数
-
云函数封装
'use strict';
exports.main = async (event, context) => {
//event为客户端上传的参数
// console.log('event : ', event)
// 这里是各种配置表的请求,主要是获取所需的信息
const db = uniCloud.database();
// 由于会获取不同表的配置,所以这里就需要直接从前端传递 表名称
const a_user = db.collection(event.dbName);
// 这里是获取数据时所需要的查询参数,过滤掉一些不需要的数据
const filter = event.filter ? event.filter : {}
let result = {};
const res_val = await a_user.where(filter).get()
result = res_val.data
//返回数据给客户端
return result
};
- 根据我写的注释,可以很清楚的看到每一个字段是干啥用的。
- 我这里配置的所有参数,都是直接去查询某张表的,所有字段都在请求时配置好,这样就不需要在请求和发送的时候都去配置相同的参数了。
根据查询信息的封装方法,我们还可以继续封装其他的,比如删除、分页等等
封装分页云函数
分页其实也是查询的一种,只是里面会多一些额外的分页参数,封装起来和查询也有点区别。
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
var dbName = event.dbName //集合表名
var order = event.order ? event.order : {} //排序
var filter = event.filter ? event.filter : {} //筛选条件
var pageIndex = event.pageIndex ? event.pageIndex : 1 //当前页数
var pageSize = event.pageSize ? event.pageSize : 15 //每页数量
};
- 在获取数据的时候,需要添加两个分页参数
pageIndex和pageSize - 其他的参数都差不多。
- 分页需要先查询出当前表的总数
let countResult = await db.collection(dbName).where(filter).count()
const total = countResult.total //得到总记录数
const totalPage = Math.ceil(total / pageSize) //计算页数
- 得到总数之后,就可以判断一下,返回给前端请求时提示它是否还有数据
var hasMore //提示前端是否还有数据
if (pageIndex > totalPage || pageIndex == totalPage) { //如果没有数据了,就返回false
hasMore = false
} else {
hasMore = true
}
- 最后可以通过上面的参数进行查询分页数据
let result = {}
if(order.name && order.type){
result = await db.collection(dbName)
.where(filter)
.skip((pageIndex - 1) * pageSize)
.limit(pageSize)
.orderBy(order.name,order.type)
.get()
}else{
result = await db.collection(dbName)
.where(filter)
.skip((pageIndex - 1) * pageSize)
.limit(pageSize)
.get()
}
result.hasMore = hasMore
return result
- 我在这里判断一下
order参数,主要用于分页后排序操作,如果没有的话,直接用else里面的代码就行了
封装删除云函数
- 删除的云函数和查询的就一样了,只是最后调用的方法不同而已
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
var dbName = event.dbName //集合表名
var filter = event.filter ? event.filter : {}//筛选条件
let result = await db.collection(dbName).where(filter).remove()
if(result.deleted === 0){
return {
success: false,
msg: '删除失败'
}
}
return {
success: true,
msg: '删除成功'
}
};
总结一下
封装云函数只是一种思路,会结合实际需求来写,当然大部分时候,都会按照最简单也是最方便的写法去写(一个表对应一个云函数)这样就不会出错,不会一直去修改封装好的云函数里面的逻辑。
如果需求比较简单的话,增删改查 + 分页,一共就五个云函数,看起来会更直观,也不需要修改多处,只需要专注于前端逻辑就好了。
如果有更简单的封装方法,也可以讨论讨论哦~~~