前言
微信云开发是微信平台功能已经出来挺久了,最近看了下云开发文档,准备动手写个小程序练练手。
前端模块使用以前写过的一个用uni-app搭建的一个项目,云开发模块就是重新搭建。
1、创建微信小程序
首先在微信开发工具创建小程序,填入你的appid,后端服务选择小程序云开发。
创建完毕,目录结构如下:
cloudfunctions
是云函数目录,miniprogram
是小程序前端模块。
因为前端模块我要使用uni-app,所以得进行改造。
把miniprogram
目录删除,把 vue-cli 创建 uni-app 项目代码复制进来,不懂怎么创建uni-app项目的点这里。
安装依赖npm i
,运行npm run dev:mp-weixin
,最终目录如下:
2、重新指定小程序前端模块目录
修改uni-app的打包输出路径:
dev 模式编译出的各平台代码存放于根目录下的 /dist/dev/目录下,
build 模式编译出的各平台代码存放于根目录下的 /dist/build/ 目录下,
对于要固定的小程序目录很不友好,我们得固定输出目录。
修改package.json
的scripts
的 dev:mp-weixin
和build:mp-weixin
命令:
"build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin UNI_OUTPUT_DIR=dist/build/mp-weixin vue-cli-service uni-build",
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin UNI_OUTPUT_DIR=dist/build/mp-weixin vue-cli-service uni-build --watch",
添加UNI_OUTPUT_DIR=dist/build/mp-weixin
,指定输出目录为dist/build/mp-weixin
再修改project.config.json
文件,把前端模块指定到dist/build/mp-weixin
:
"miniprogramRoot": "dist/build/mp-weixin/",
修改完成,打开微信开发工具,小程序就可以运行了。
3、云开发
初始化
在云开发设置面板,新建个环境,后面的env取环境ID
小程序端
在src/main.js 添加初始化方法
wx.cloud.init({
env: '5175aa', //环境
traceUser: true, //是否在将用户访问记录到用户管理中,在控制台中可见
})
云函数端
// 初始化 cloud
cloud.init({
// API 调用都保持和云函数当前所在环境一致
// env: cloud.DYNAMIC_CURRENT_ENV
env: '5175aa'
})
4、编写第一个云函数
云函数
我们把cloudfunctions
文件夹下的文件都删除,新建个main
云函数:
config.json
{
"permissions": {
"openapi": []
}
}
package.json
{
"name": "echo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"wx-server-sdk": "~2.4.0"
}
}
index.js
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
// API 调用都保持和云函数当前所在环境一致
// env: cloud.DYNAMIC_CURRENT_ENV
env: '5175aa'
})
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
return {
event,
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
}
}
一个云函数就完成了,我们现在可以进行本地调试,或者上传到云端部署。
本地调试步骤
需要进入cloudfunctions/main
目录下,安装依赖
npm i
再右键选择开启云函数本地调试
上传到云端部署
小程序端调用
wx.cloud.callFunction({
// 云函数名称
name: 'mian',
// 传给云函数的参数
data: {
a: 1,
b: 2,
},
success: function(res) {
console.log(res.result.sum) // 3
},
fail: console.error
})
当然,Promise 风格的调用也是支持的:
wx.cloud.callFunction({
// 云函数名称
name: 'main',
// 传给云函数的参数
data: {
a: 1,
b: 2,
},
})
.then(res => {
console.log(res.result) // 3
})
.catch(console.error)
请求成功。
5、云函数路由优化tcb-router
云函数也有不少缺点:
-
一个微信小程序只能创建50个云函数,不能满足复杂业务需求。
-
每个云函数都都需要维护一份
package.json
所以我们需要用tcb-router
进行优化,tcb-router
是一个koa风格的云函数路由库。
安装tcb-router
:
在cloudfunctions/main
目录下
npm i tcb-router -S
在cloudfunctions/main/index.js
修改成:
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router')
cloud.init({
// API 调用都保持和云函数当前所在环境一致
// env: cloud.DYNAMIC_CURRENT_ENV
env: '5175aa'
})
// 云函数入口函数
exports.main = async(event, context) => {
const app = new TcbRouter({
event
})
//全局中间件
app.use(async(ctx, next) => {
console.log('进入全局中间件')
await next()
console.log('退出全局中间件')
})
app.router('add', async(ctx, next) => {
ctx.body = {
data: '新增成功'
}
})
app.router('movie', async(ctx, next) => {
ctx.body = {
data: '输出'
}
})
return app.serve()
}
小程序端调用
wx.cloud.callFunction({
name: 'main',
data: {
$url: 'add'
},
}).then((res) => {
console.log(res)
})
wx.cloud.callFunction({
name: 'main',
data: {
$url: 'movie'
},
}).then((res) => {
console.log(res)
})
云函数模块化
我们可以把路由的实现抽离成一个个js文件:
在cloudfunctions/main
下新建common/index.js
exports.login = async (ctx, next) => {
console.log(ctx.cloud)
console.log(ctx.db)
ctx.body = {
data: '输出'
}
}
在cloudfunctions/main/index.js
中,用require
导入,并且可以把cloud
、db
对象挂载到ctx对象下,在实现模块就可以使用ctx.cloud
、ctx.db
调用对象
// 云函数模板
// 部署:在 cloud-functions/login 文件夹右击选择 “上传并部署”
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router');
// 公共模块
const common = require('./common/index')
// 初始化 cloud
cloud.init({
// API 调用都保持和云函数当前所在环境一致
// env: cloud.DYNAMIC_CURRENT_ENV
env: '5175aa'
})
const db = cloud.database()
exports.main = async (event, context) => {
const app = new TcbRouter({event});
// app.use 表示该中间件会适用于所有的路由
app.use(async (ctx, next) => {
ctx.db = db;
ctx.cloud = cloud;
console.log('进入全局中间件')
await next()
console.log('退出全局中间件')
});
//授权登录
app.router('/login', common.login)
return app.serve();
}
6、全局异常捕捉中间件
到现在为止,可以进行应用开发了,但使用过koa的人都知道,我们还差个全局异常捕捉中间件,来统一处理服务器报错问题。
新建个工具类utils/index.js
module.exports = {
// 手动报错
throwError(code = 400, msg = '服务器错误') {
const err = new Error(msg);
err.code = code;
err.msg = msg;
throw err;
},
};
在cloudfunctions/main/index.js
const utils = require('./utils/index')
// app.use 表示该中间件会适用于所有的路由
app.use(async (ctx, next) => {
ctx.db = db;
ctx.cloud = cloud;
ctx.utils=utils //挂载工具类
try {
await next(); //在下个环节报错就抛出错误
} catch (err) {
// 手动抛出异常 throwError函数触发
if (err.msg) {
ctx.body = {
code: err.code,
data: '',
msg: err.msg,
};
} else {
//自动报错
ctx.body = {
code: 500,
data: '',
msg: '服务器内部错误:' + err,
};
}
}
});
测试
手动抛出异常
exports.login = async (ctx, next) => {
ctx.uilts.throwError('500','手动抛出异常')
ctx.body = {
data: '输出'
}
}
返回成功
内部错误异常
exports.login = async (ctx, next) => {
console.log(a); //错误 不存在a变量
ctx.body = {
data: '输出'
}
}
返回成功
7、数据库的增、删、查、改
云开发的数据库,前端和云函数都可以进行操作,但在前端进行数据库操作有比较大的缺点:
- 请求列表数据,直接操作数据库每次只能返回20条,云函数的话可以返回100条;
- 还有就是直接调用数据库,所有的增删改查运算操作都是在手机本地运行的,数据量大的话,会耗用用户流量,而云函数则是在微信服务器上运算的。
- 安全问题,可能会被恶意攻击
所以还是在云函数进行数据库操作。
初始化
在云开发面板,新建个集合user(表)
在云函数初始化
const db = cloud.database()
插入数据
db.collection('user').add({
// data 字段表示需新增的 JSON 数据
data: {
// _id: 'todo-identifiant-aleatoire', // 可选自定义 _id,在此处场景下用数据库自动分配的就可以了
description: "learn cloud database",
due: new Date("2018-09-01"),
tags: [
"cloud",
"database"
],
// 为待办事项添加一个地理位置(113°E,23°N)
location: new db.Geo.Point(113, 23),
done: false
},
success: function(res) {
// res 是一个对象,其中有 _id 字段标记刚创建的记录的 id
console.log(res)
}
})
获取一个记录的数据
db.collection('user').doc('todo-identifiant-aleatoire').get().then(res => {
// res.data 包含该记录的数据
console.log(res.data)
})
获取多个记录的数据
我们也可以一次性获取多条记录。通过调用集合上的 where 方法可以指定查询条件,再调用 get 方法即可只返回满足指定查询条件的记录,比如获取用户的所有未完成的待办事项:
db.collection('user').where({
_openid: 'user-open-id',
done: false
})
.get({
success: function(res) {
// res.data 是包含以上定义的两条记录的数组
console.log(res.data)
}
})
更新数据
db.collection('user').doc('todo-identifiant-aleatoire').update({
// data 传入需要局部更新的数据
data: {
// 表示将 done 字段置为 true
done: true
},
success: function(res) {
console.log(res.data)
}
})
删除一条记录
db.collection('user').doc('todo-identifiant-aleatoire').remove({
success: function(res) {
console.log(res.data)
}
})
更多用法可以去查看微信官方文档
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!