🌟前言
哈喽小伙伴们,小程序的新星计划在这周也进入了尾声,回顾一个月输出小程序相关文章以来,收获颇多充实了很多;今天这篇文章将结合官方文档带大家来了解一下微信小程序的云开发;话不多说,咱们直接开整!🤘
🌟微信云开发
微信云开发是微信团队联合腾讯云推出的专业的小程序开发服务。
开发者可以使用云开发快速开发小程序、小游戏、公众号网页等,并且原生打通微信开放能力。
开发者无需搭建服务器,可免鉴权直接使用平台提供的 API 进行业务开发。
🌟创建第一个云开发项目
🌟准备工作
下载并安装微信开发者工具;
注册微信小程序,获取小程序的 AppID(开发管理-开发设置);
🌟第 1 步:创建项目
打开并登录微信开发者工具,新建小程序项目,填入 AppID,后端服务选择“微信云开发”并勾选同意"云开发服务条款":
点击创建后,即可得到一个展示云开发基础能力的示例小程序:
🌟第 2 步:开通云开发,创建环境
在使用云开发能力之前,需要先开通云开发。
在开发者工具的工具栏左侧,点击 “云开发” 按钮即可打开云控制台,根据提示开通云开发,并且创建一个新的云开发环境。
每个环境相互隔离,拥有唯一的环境 ID,包含独立的数据库实例、存储空间、云函数配置等资源;初始创建的环境自动成为默认环境;默认配额下可以创建两个环境;腾讯云控制台创建的云开发环境也可在微信云开发中使用。登录微信云开发控制台-设置-环境设置,点击环境名称,选择“管理我的环境”,点击“使用已有腾讯云环境”按钮,选择所需腾讯云环境,即可在微信云开发控制台使用该环境。
🌟第 3 步:开始开发
开通创建环境后,即可以开始在模拟器上操作小程序体验云开发提供的部分基础能力演示。
🌟后续步骤
您可以参考以下文档继续开发:
- 使用 云数据库 存储、查询、推送数据;
- 使用 存储 对文件进行存储;
- 使用 云函数 运行后端代码;
- 使用 云托管 部署后台服务;
- 使用 云调用 调用微信开放接口;
- 使用 内容管理(CMS) 管理后台数据;
- 使用 静态网站 部署网站。
🌟第三方快速注册的小程序
通过第三方快速注册的小程序也支持开通并使用云开发,可通过接口开通以及控制台操作开通;
🌟使用低代码编辑器搭建小程序
🌟第1步: 创建项目
打开并登录微信开发者工具,新建小程序项目,填入 AppID,后端服务选择“微信云开发”。
🌟第2步: 选择模板
在模板来源中选择微搭,并在下方选择希望使用的低代码模板。
以网购消费者市场调研模板为例,点击确定后即可进入到该模板的低代码编辑器中。
🌟第3步: 开始开发
进入低代码编辑后,您便可以通过简单的组件拖拉拽以及可视化界面对模板进行定制化的开发。
🌟微信云开发优势
🌟微信云开发能力
云数据库: 文档型数据库,稳定可靠;支持在小程序端和云函数中调用。存储: 云端文件存储,自带 CDN 加速,支持在前端直接上传/下载,可在云开发控制台可视化管理。云函数: 在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码。静态网站: 快速部署网站,支持自定义域名、网站防刷等配置。内容管理(CMS): 一键部署,可视化管理文本、Markdown、图片等多种内容,使用云数据库读取数据并使用数据。
🌟云数据库
任何一个大型的应用程序和服务,都必须会使用到高性能的数据存储解决方案,用来准确(ACID,原子性 Atomicity、一致性 Consistency、隔离性 Isolation、持久性 Durability,可以拓展了解一下)、快速、可靠地存储和检索用户的账户信息、商品以及商品交易信息、产品数据、资讯文章等等等等,而云开发就自带高性能、高可用、高拓展性且安全的数据库。
🌟基础知识
在操作数据库时,我们要对数据库database、集合collection、记录doc以及字段field要有一定的了解,首先要记住这些对应的英文单词,当你要操作某个记录doc的字段内容时,就像投送快递一样,要先搞清楚它到底在哪个数据库、在哪个集合、在哪个记录里,一级一级的去找。操作数据库通常都是对数据库、集合、记录、字段进行增、删、改、查,当你清楚了这些,操作数据库就不会迷糊了。
🌟云数据库与 Excel、MySQL 的对应理解
我们可以结合 Excel 以及 MySQL(之前没有接触过 MySQL 也没有关系,只看与 Excel 的对应就行)来理解云开发的数据库。
🌟集合的创建与数据类型
我们现在来创建一个 books 的集合(相当于创建一张 Excel 表),用来存放图书馆里面书籍的信息,比如这样一本书:
打开云开发控制台的数据库标签,新建集合 books,然后选择该集合,给 books 里添加记录(类似于填写 Excel 含字段的第一行和其中一行关于书的信息记录),依次添加字段:
字段名:title,类型:string,值: JavaScript 权威指南(第 6 版)字段名:author,类型:string,值:弗兰纳根(David Flanagan)字段名:isbn,类型:string,值:9787111376613字段名:publishInfo,类型:object然后我们再在 publishInfo 的下面(二级)添加字段 press,类型为 string,值为:机械工业出版社;year,类型为 number,值为:2012
另外,如需批量添加数据库集合中的记录时,推荐使用云开发数据库自带的“高级操作”,高级操作支持数据库的增删改查以及聚合等操作,可有效提高数据库管理效率。
🌟云数据库CURD
🌟初始化
在开始使用数据库 API 进行增删改查操作之前,需要先获取数据库的引用。以下调用获取默认环境的数据库的引用:
const db = wx.cloud.database()
如需获取其他环境的数据库引用,可以在调用时传入一个对象参数,在其中通过 env 字段指定要使用的环境。此时方法会返回一个对测试环境数据库的引用。
示例:假设有一个环境名为 test,用做测试环境,那么可以如下获取测试环境数据库:
const testDB = wx.cloud.database({ env: 'test' })
要操作一个集合,需先获取它的引用。在获取了数据库的引用后,就可以通过数据库引用上的 collection 方法获取一个集合的引用了,比如获取待办事项清单集合:
const todos = db.collection('todos')
获取集合的引用并不会发起网络请求去拉取它的数据,我们可以通过此引用在该集合上进行增删查改的操作,除此之外,还可以通过集合上的 doc 方法来获取集合中一个指定 ID 的记录的引用。同理,记录的引用可以用于对特定记录进行更新和删除操作。
假设我们有一个待办事项的 ID 为 todo-identifiant-aleatoire,那么我们可以通过 doc 方法获取它的引用:
const todo = db.collection('todos').doc('todo-identifiant-aleatoire')
🌟插入数据
可以通过在集合对象上调用 add 方法往集合中插入一条记录。还是用待办事项清单的例子,比如我们想新增一个待办事项:
db.collection('todos').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) } })
当然,Promise 风格也是支持的,只要传入对象中没有 success, fail 或 complete,那么 add 方法就会返回一个 Promise:
db.collection('todos').add({ // data 字段表示需新增的 JSON 数据 data: { description: "learn cloud database", due: new Date("2018-09-01"), tags: [ "cloud", "database" ], location: new db.Geo.Point(113, 23), done: false } }) .then(res => { console.log(res) })
数据库的增删查改 API 都同时支持回调风格和 Promise 风格调用。
在创建成功之后,我们可以在控制台中查看到刚新增的数据。
🌟查询数据
在记录和集合上都有提供 get 方法用于获取单个记录或集合中多个记录的数据。
假设我们已有一个集合 todos,其中包含以下格式记录:
db.collection('todos').add({ // data 字段表示需新增的 JSON 数据 data: { description: "learn cloud database", due: new Date("2018-09-01"), tags: [ "cloud", "database" ], location: new db.Geo.Point(113, 23), done: false } }) .then(res => { console.log(res) })
🌟获取一个记录的数据
我们先来看看如何获取一个记录的数据,假设我们已有一个 ID 为 todo-identifiant-aleatoire 的在集合 todos 上的记录,那么我们可以通过在该记录的引用调用 get 方法获取这个待办事项的数据:
db.collection('todos').doc('todo-identifiant-aleatoire').get({ success: function(res) { // res.data 包含该记录的数据 console.log(res.data) } }) 也可以用 Promise 风格调用: db.collection('todos').doc('todo-identifiant-aleatoire').get().then(res => { // res.data 包含该记录的数据 console.log(res.data) })
🌟获取多个记录的数据
我们也可以一次性获取多条记录。通过调用集合上的 where 方法可以指定查询条件,再调用 get 方法即可只返回满足指定查询条件的记录,比如获取用户的所有未完成的待办事项:
db.collection('todos').where({ _openid: 'user-open-id', done: false }) .get({ success: function(res) { // res.data 是包含以上定义的两条记录的数组 console.log(res.data) } })
where 方法接收一个对象参数,该对象中每个字段和它的值构成一个需满足的匹配条件,各个字段间的关系是 “与” 的关系,即需同时满足这些匹配条件,在这个例子中,就是查询出 todos 集合中 _openid 等于 user-open-id 且 done 等于 false 的记录。在查询条件中我们也可以指定匹配一个嵌套字段的值,比如找出自己的标为黄色的待办事项:
db.collection('todos').where({ _openid: 'user-open-id', style: { color: 'yellow' } }) .get({ success: function(res) { console.log(res.data) } })
也可以用 “点表示法” 表示嵌套字段:
db.collection('todos').where({ _openid: 'user-open-id', 'style.color': 'yellow' }) .get({ success: function(res) { console.log(res.data) } })
🌟获取一个集合的数据
如果要获取一个集合的数据,比如获取 todos 集合上的所有记录,可以在集合上调用 get 方法获取,但通常不建议这么使用,在小程序中我们需要尽量避免一次性获取过量的数据,只应获取必要的数据。为了防止误操作以及保护小程序体验,小程序端在获取集合数据时服务器一次默认并且最多返回 20 条记录,云函数端这个数字则是 100。开发者可以通过 limit 方法指定需要获取的记录数量,但小程序端不能超过 20 条,云函数端不能超过 100 条。
db.collection('todos').get({ success: function(res) { // res.data 是一个包含集合中有权限访问的所有记录的数据,不超过 20 条 console.log(res.data) } })
也可以用 Promise 风格调用:
db.collection('todos').get().then(res => { // res.data 是一个包含集合中有权限访问的所有记录的数据,不超过 20 条 console.log(res.data) })
下面是在云函数端获取一个集合所有记录的例子,因为有最多一次取 100 条的限制,因此很可能一个请求无法取出所有数据,需要分批次取:
const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() const MAX_LIMIT = 100 exports.main = async (event, context) => { // 先取出集合记录总数 const countResult = await db.collection('todos').count() const total = countResult.total // 计算需分几次取 const batchTimes = Math.ceil(total / 100) // 承载所有读操作的 promise 的数组 const tasks = [] for (let i = 0; i < batchTimes; i++) { const promise = db.collection('todos').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get() tasks.push(promise) } // 等待所有 return (await Promise.all(tasks)).reduce((acc, cur) => { return { data: acc.data.concat(cur.data), errMsg: acc.errMsg, } }) }
🌟更新数据
更新数据主要有两个方法:
API | 说明 |
update | 局部更新一个或多个记录 |
set | 替换更新一个记录 |
🌟局部更新
使用 update 方法可以局部更新一个记录或一个集合中的记录,局部更新意味着只有指定的字段会得到更新,其他字段不受影响。
db.collection('todos').doc('todo-identifiant-aleatoire').update({ // data 传入需要局部更新的数据 data: { // 表示将 done 字段置为 true done: true }, success: function(res) { console.log(res.data) } })
除了用指定值更新字段外,数据库 API 还提供了一系列的更新指令用于执行更复杂的更新操作,更新指令可以通过 db.command 取得:
更新指令 | 说明 |
set | 设置字段为指定值 |
remove | 删除字段 |
inc | 原子自增字段值 |
mul | 原子自乘字段值 |
push | 如字段值为数组,往数组尾部增加指定值 |
pop | 如字段值为数组,从数组尾部删除一个元素 |
shift | 如字段值为数组,从数组头部删除一个元素 |
unshift | 如字段值为数组,往数组头部增加指定值 |
const _ = db.command db.collection('todos').doc('todo-identifiant-aleatoire').update({ data: { // 表示指示数据库将字段自增 10 progress: _.inc(10) }, success: function(res) { console.log(res.data) } })
用 inc 指令而不是取出值、加 10 再写进去的好处在于这个写操作是个原子操作,不会受到并发写的影响,比如同时有两名用户 A 和 B
取了同一个字段值,然后分别加上 10 和 20 再写进数据库,那么这个字段最终结果会是加了 20 而不是 30。如果使用 inc
指令则不会有这个问题。
如果字段是个数组,那么我们可以使用 push、pop、shift 和 unshift 对数组进行原子更新操作,比如给一条待办事项加多一个标签:
const _ = db.command db.collection('todos').doc('todo-identifiant-aleatoire').update({ data: { tags: _.push('mini-program') }, success: function(res) { console.log(res.data) } })
可能读者已经注意到我们提供了 set 指令,这个指令有什么用呢?这个指令的用处在于更新一个字段值为另一个对象。比如如下语句是更新 style.color 字段为 ‘blue’ 而不是把 style 字段更新为 { color: ‘blue’ } 对象:
const _ = db.command db.collection('todos').doc('todo-identifiant-aleatoire').update({ data: { style: { color: 'blue' } }, success: function(res) { console.log(res.data) } })
如果需要将这个 style 字段更新为另一个对象,可以使用 set 指令:
const _ = db.command db.collection('todos').doc('todo-identifiant-aleatoire').update({ data: { style: _.set({ color: 'blue' }) }, success: function(res) { console.log(res.data) } })
如果需要更新多个数据,需在 Server 端进行操作(云函数),在 where 语句后同样的调用 update 方法即可,比如将所有未完待办事项的进度加 10%:
// 使用了 async await 语法 const cloud = require('wx-server-sdk') const db = cloud.database() const _ = db.command exports.main = async (event, context) => { try { return await db.collection('todos').where({ done: false }) .update({ data: { progress: _.inc(10) }, }) } catch(e) { console.error(e) } }
🌟替换更新
如果需要替换更新一条记录,可以在记录上使用 set 方法,替换更新意味着用传入的对象替换指定的记录:
const _ = db.command db.collection('todos').doc('todo-identifiant-aleatoire').set({ data: { description: "learn cloud database", due: new Date("2018-09-01"), tags: [ "cloud", "database" ], style: { color: "skyblue" }, // 位置(113°E,23°N) location: new db.Geo.Point(113, 23), done: false }, success: function(res) { console.log(res.data) } })
如果指定 ID 的记录不存在,则会自动创建该记录,该记录将拥有指定的 ID。
🌟删除数据
在这章节我们一起看看如何使用数据库 API 完成数据删除,在本节中我们还是沿用读取数据章节中使用的数据。
🌟删除一条记录
对记录使用 remove 方法可以删除该条记录,比如:
db.collection('todos').doc('todo-identifiant-aleatoire').remove({ success: function(res) { console.log(res.data) } })
🌟删除多条记录
如果需要更新多个数据,需在 Server 端进行操作(云函数)。可通过 where 语句选取多条记录执行删除,只有有权限删除的记录会被删除。比如删除所有已完成的待办事项:
// 使用了 async await 语法 const cloud = require('wx-server-sdk') const db = cloud.database() const _ = db.command exports.main = async (event, context) => { try { return await db.collection('todos').where({ done: true }).remove() } catch(e) { console.error(e) } }
在大多数情况下,我们希望用户只能操作自己的数据(自己的代表事项),不能操作其他人的数据(其他人的待办事项),这就需要引入权限控制了。
🌟写在最后
这篇文章给大家讲解了一下在小程序当中的云开发,更多小程序文章请大家持续关注,尽请期待。各位小伙伴让我们 let’s be prepared at all times!