在开发微信小程序时,使用传统的操作云数据库的方法有很多缺点,比如代码冗余不好维护修改,所以现在都是基于云函数来操作数据库或者其他逻辑。正好我在做一个集合商城、垃圾分类、后台系统的微信小程序模板,通过这个案列我们来学习一下云函数。也方便我以后直接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 }) } }