在开发微信小程序时,使用传统的操作云数据库的方法有很多缺点,比如代码冗余不好维护修改,所以现在都是基于云函数来操作数据库或者其他逻辑。正好我在做一个集合商城、垃圾分类、后台系统的微信小程序模板,通过这个案列我们来学习一下云函数。也方便我以后直接copy。
需要的工具:
1、node.js
2、tcb-router
这里默认大家会node.js基本知识不再多说
打开微信小程序点云开发生成的模板,右击cloudfunctions新建node.js云函数函数名为db(意思为操作数据库的函数都在这),新建完成后系统会自动生成模板,右击db在外部终端窗口打开
安装tcb-router : npm install --save tcb-router
安装完成打开db的package.json,会看到如下证明安装成功
需要的代码:
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router');
cloud.init({
env: "dd-aqou2"
})
let db = cloud.database()
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
let {
APPID,
OPENID
} = wxContext
const app = new TcbRouter({
event
})
app.use(async (ctx, next) => {
ctx.data = {};
await next(); // 执行下一中间件
});
return app.serve();
}
这样就搭建好了基本框架,接下来要写登录逻辑,我的前端运用的小程序wx.getUserProfile的api来获取用户信息,这样我们就得到了userInfo,点击登录时连接user的数据库,数据库每个用户唯一标识是openid,如果数据库有这个openid,则更新用户信息,没有则创建新用户。运用tcb-router时,我遇到一个小问题,就是值取别的名字赋值不到,所以我都是用ctx.data.xxx来命名返回值。先看效果图:
没登录时不能点击其他按钮:
接下来我们看云函数的逻辑:
// 用户登录
app.router("login", async (ctx, next) => {
let {
userInfo
} = event
// 连接数据库user
let user = db.collection('user')
let {
total
} = await user.where({
OPENID: OPENID
}).count()
if (total) {
await user.where({
OPENID: OPENID
})
.update({
data: userInfo
})
} else {
await user.add({
data: {
nickName: userInfo.nickName,
gender: userInfo.gender,
avatarUrl: userInfo.avatarUrl,
OPENID: OPENID,
integral: 0, //总积分
signTotal: 0, //连续签到天数
signday: [] //签到日期
}
})
}
let {
data
} = await user.where({
OPENID: OPENID
}).get()
ctx.data.rank = await user.orderBy('integral', 'desc').get()
ctx.body = {
code: 0,
msg: "添加成功",
userInfo: data[0],
rank: ctx.data.rank
}
return
});
接着我们在小程序端调用云函数(别忘记部署云函数,右击db上传并部署,云端安装依赖)
找到登录按钮事件
/**
* 获取用户信息
*/
handleGetUserInfo(e) {
wx.getUserProfile({
desc: '用于完善个人资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
this.setData({
cloudID: res.cloudID,
})
wx.cloud.callFunction({
// 要调用的云函数名称
name: "db",
// 传递给云函数的参数
data: {
$url: "login", // 要调用的路由的路径,传入准确路径或者通配符*
userInfo: res.userInfo,
},
success: (res) => {
this.setData({
userInfo: res.result.userInfo
})
this.getRank(res.result.rank.data)
},
});
},
fail: (res) => {}
})
},
因为我是主攻前端的,后端的知识也不扎实所以排名的逻辑我放在了前端
/**
* 获取排名
*/
getRank(arr) {
for (let i = 0; i < arr.length; i++) {
if (this.data.userInfo.OPENID === arr[i].OPENID)
this.setData({
rank: i + 1
})
}
}