文章很长,建议先收藏,有充分的时间再学习,没有小程序基础的,也阔以先收藏哦。
本文章会手把手带各位小伙伴入门微信小程序云开发,因为我还不是全栈工程师,所以不是特别清楚前后端分离模式下,后端工程师需要做的具体事情,所以我就不扯普通开发模式和云开发模式的区别了以及其他相关的理论知识了,不过各位放心,我有信心教会各位怎么在实际项目中使用云开发模式。 ٩͡( 。ớ ₃ờ)۶呵呵
下面这张图是我自己理解的云函数开发模式,大家阔以瞄瞄。(づ◡ど)
1、 首先云开发给我们提供了三大功能:
集合
,也就是存放请求接口的数据,目前只支持导入导出JSON
和CSV
格式文件。File ID
的云路径用于前端访问资源,像image、video等标签可以直接使用。node.js
语言,支持npm(云函数函数的编写也是在本地目录的,然后上传到服务器很方便,不用搭建环境,点击目录右键上传即可)。2、其次等我们写完静态代码后,就可以用官方封装好的方法去调用数据库的集合了,相当于https请求接口的过程,请求的方式有两种,一是直接请求,但是一次请求会有返回数据20条限制,二是通过云函数去请求,返回的限制会宽一点,是100条,再多的话可能就需要通过循环去获取了。
3、如果请求的数据是图片、视频等资源,可以先手动上传到云存储,然后把资源的File ID存放到集合的字段里就好了,因为File ID只支持小程序的部分标签,所以如果是background-image这种需要用https路径的,云存储还会有一个叫下载地址的供使用。
4、最后是增删改查,和请求接口一样官方都封装好了相关方法,可以直接请求修改数据,但是因为数据库的每一个集合都会有权限的限制,所以会遇到很多情况导致请求失败,比如某条数据不是自己创建的,导致无权修改。所以,一般要复杂的增删改查都会用云函数去调用。
首先我们打开微信开发者工具,新建一个云项目,然后AppID不可以用测试号,都开始学云开发了,我就默认各位已注册小程序号了,AppID的话自己去微信公众平台的开发菜单拿一下就好了,然后后台服务选择云开发。
然后我为了对比我创建了一个普通项目和一个云项目,可以从图中看到,因为普通项目用的是测试AppID,所以会少了一个云开发的按钮,项目目录的话有所改变,多了一个叫cloudfunctions的文件夹和README.md文件,原本的小程序项目外也多包裹了一次miniprogram文件夹,然后看模拟器就可以看到官方给出了很多调用数据的例子,但是我建议把文章学完后再自己过一遍,这样容易懂多了。
接着我们先去个理发店,把项目没用的删了,从头开始,经过洗剪吹后,变成了下面这个样子。然后我们可以很清晰看到,cloudfunctions就是用来存放云函数的本地文件夹,miniprogram就是用来存放小程序的文件夹,至于README.md相当于说明书,不用理。
然后打开project.config.json文件,你会发现多了"miniprogramRoot": "miniprogram/"
、"cloudfunctionRoot": "cloudfunctions/"
,这两行代码,这两分别指向的是小程序的工作目录、云函数的工作目录,
接着在看一下app.js文件,我把左边普通项目进入小程序获取用户信息的代码注销了,对比一下云项目可以看到,云项目在进入项目时会多了一步判断云环境的初始化代码。
所以如果你想在普通项目中使用云开发,配置一下project.config.json文件
的两参数和在app.js文件
初始云环境就好了,当然AppID也必须是正式的,不然开发工具的云开发按钮是不会显示的。
然后点击开发者工具顶部的按钮,如果没有开通过会弹出下面的页面,点击开通,然后需要新建一个云环境,根据就说明一步步认真填写,因为一个小程序号最多可以创建两个环境,并且销毁环境很麻烦,需要通过官方那边,环境版本先用基础版就好了。
环境创建完后我们就进入云开发控制台了,可以看到,我们要用的数据库、云存储、云函数三个主要功能都在里面了,我们现在先不讲这三个的实操先,我们得先让小程序端绑定这个云环境。
我们点击设置菜单,然后可以看见我的当前使用的环境,以及我们当前环境的ID,当前环境配额我已经选了按量付费,因为刚创建的环境只有3个月的试用期,如果你怕环境过期可以顺便开通一下,按量付费的话要超过一定额度才会收费,对于我们普通用户的小程序可以说是免费的,需要注意的是切换付费方式的间隔是一个月一次哦。
然后我们回到小程序这边,打开app.js文件
,在env参数上填写你创建的环境ID,这样我们的小程序在初始化时就会默认指向我们创建的环境了。
然后我把鼠标移到cloudfunctions文件夹上右击,然后点击当前环境,然后再选择你创建的环境就好了,我这个小程序号创建了两个环境,所以有两个选项,操作这里的目的是我们后期在这个文件夹写了云函数后上传到云服务器需要有一个指定的目标环境。(如果你点击当前环境后发现并没有可选择的环境,则可以重新打开项目后尝试,如果还是没有,就需要再等一会,新创建的环境会有个十来分钟的延迟)
好了,到这里我们就已经把云项目搭建好了,后面就开始进入我是谁、我在哪儿环节了。(╯°Д°)╯︵┻━┻
为了缩短文章的篇幅,我就不一一的去打代码了,教会大家使用小程序文档,在开发上就算是ojbk了,当然,一些要点我也会说一下,官方文档链接也会给,具体操作我也会录制成GIF,所以小伙伴们不要惊慌!!
首先我要提前说一下Collection这个数据库集合的引用,嗯,我个人认为学会下面表格的方法,你就已经算是掌握小程序云数据库操作的基础了,首先我们看一下add
(增)、remove
(删)、update
(改)、get
(查)我相信各位一看英文就会明白了,接着是doc
,它只接收_id
,这意味着只能精准的用于操作集合中的某条数据,它可以配合增删改查对指定的某条数据进行一系列的操作,最后是where
,与doc相比where比较适合用于操作多条数据,比如一些数据的筛选、模糊搜索都可以用where。
方法 | 官方描述 |
---|---|
Collection.get(): Promise | 查: 获取集合数据,或获取根据查询条件筛选后的集合数据。 |
Collection.add(options: Object): Promise | 增: 新增记录,如果传入的记录对象没有 _id 字段,则由后台自动生成 _id;若指定了 _id,则不能与已有记录冲突 |
Collection.remove(): Promise | 删: 删除多条记录。注意只支持通过匹配 where 语句来删除,不支持 skip 和 limit。 |
Collection.update(): Promise | 改: 更新多条记录 |
Collection.doc(id: string): Document | 获取集合中指定记录的引用。方法接受一个 id 参数,指定需引用的记录的 _id。 |
Collection.where(condition: Object): Collection | 指定查询条件,返回带新查询条件的新的集合引用 |
Collection数据库集合引用支持的所有方法
在进行增删改查操作前,我们要养成习惯,在js最外层先定义一个全局的数据库引用
// 养成习惯,先在最外层定义数据库引用
const db = wx.cloud.database();
Page({
/**
* 页面的初始数据
*/
data: {},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {},
})
然后我们调用返回接受参数的方式有两种,以获取数据的get()
方法为例子,第一种是在get()
里面传一个对象,对象里可以有成功的success
参数和失败的fail
参数,用逗号分开,然后我们就可以拿到云数据库集合里的记录了,collection()
方法是用来绑定要查询的集合。
db.collection('集合名').get({
success: function (res) {
console.log(res)
},
fail: function (err) {
console.log(err)
}
})
//箭头函数简写
db.collection('集合名').get({
success: res => {
console.log(res)
},
fail: err => {
console.log(err)
}
})
然后第二种是用 Promise 风格调用,当我们get()
不传入参数时,就可以直接用.then()
来接受成功后的返回值,紧跟着用 .catch()
来监听失败返回的值,这种方式学过vue的小伙伴可能不会陌生,如果有小伙伴不懂的要举手示意,我会很诚实的告诉你,我也不懂,嗯哼, ψ(._.)> 谁来教我==》菜鸟教学Promise对象、MDN-Promise
好了,如果后面出现了这种形式的使用,请不要惊慌!!。
db.collection('集合名').get()
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
既然要请求数据,那么数据库必须得有数据吧,所以我们先在数据库新建一个叫水果的集合,添加两条记录,添加记录时会有一个叫文档ID的,你可以自己定义这个_id
,通常是直接用随机生成的,相当于是这条数据的身份证,它是无序的
,如果你要有序的可以自己另外去定义,然后定义的类型要用到的都会有,像字符串、数字、对象、数组都可以设置,我这就不弄复杂的数据先了。
如果GIF太快跟不上节奏可以先把文件下载到电脑本地,然后下载个2345看图王软件,它可以暂停着看
复制粘贴传送门:微信官方文档-数据库-查
从GIF中我们可以看到,获取一个集合的数据用db.collection('集合名').get()
就可以了,然后再第一次调用时你会发现返回的数组是空的,是因为在创建一个集合时默认是只有创建者可读写,所以在创建集合时可以先设置用户的访问权限,然后你可看到不管是用那种方式去接受返回值,返回的值都是一样的,另外一次返回的记录最多20条。
复制粘贴传送门:微信官方文档-数据库-增
从GIF中我们可以看到,向一个集合中插入数据用db.collection('集合名').add()
就可以了,然后add()方法里面要传一个data对象,然后data对象里面便是我们要追加集合的参数,_id可以自定义,但是如果集合中存在了相同的_id名会报错,所以可以不传,后台会自动生成,接着你会发现多了一个_openid
参数,是的,只要是小程序端插入的数据,后台都会默认添加上创建者的用户ID的。
复制粘贴传送门:微信官方文档-数据库-删
从GIF中我们可以看到, 要删除集合中的记录要用到db.collection('集合名').doc('指定记录的_id').remove()
,但是在小程序端直接操作还是会有限制的,只能用doc()
去删除指定的某条数据,不可以用where()
删除多条。
复制粘贴传送门:微信官方文档-数据库-改
从GIF中我们可以看到, 要删除集合中的记录要用到db.collection('集合名').doc('指定记录的_id').update()
,但是需要注意的是在小程序端直接操作更新数据时是有局限性的,只有权限为所有用户可读可写的数据才可以更新,然后数据库 API 还提供了一系列更新指令可以自行去啃一下。
既然要用云函数,那总得要有云函数给我们调用吧,所以我们先尝试创建一个叫add的相加云函数,从GIF中可以看到,创建完后会有一个默认的模板项目,其中config.json和package.json是配置文件,js文件才是写云代码的地方,然后js文件会有一个默认的例子,是用来获取用户是openid、appid等信息的,并且在第一次创建云函数时会自动上传到云服务器,然后我们就可以用 wx.cloud.callFunction({name:'云函数名',})
去调用云函数了,从下图中可以看出确实轻而易举就可以获取的openid,然后callFunction方法除了传一个函数名以外还可以传一个data数据,然后云函数上的event就是我们传入的data数据值,执行完后用return返回就好了。
传送门:微信官方文档-我的第一个函数
接着你会发现新创建的云函数中出现了async函数,是的,这意味着我们又可以学习新东西了,来来来发资料了(o゚v゚)ノ==》菜鸟教学async函数
好了,如果不想了解太深,那么只需要知道在async函数里面可以配合await等待一个 Promise 对象,简单点来说就是执行上下文如果遇到await,就会停下来,把它紧跟的东西(Promise 对象)执行完了,才会继续执行后面的代码,下面我就举亿个简单的例子吧:
function test() {
setTimeout(() => {
console.log('A')
},1000)
console.log('B')
}
test()
//B
//A
我相信都会知道是先输出了B,然后一秒后再输出A,那么问题来了,我要怎么做才可以让它先输出完A,再输出B?
紧跟着再看一下下面改造后的代码:
async function test() {
await new Promise(resolve => {
setTimeout(() => {
console.log('A')
resolve()//resolve的作用是把Promise的状态改为已完成
}, 1000)
})
console.log('B')
}
test()
//A
//B
结果是等待一秒后输出A,紧接着输出B,那问题又来了这有啥子意义?比如当我们有两个ajax网络请求时,请求1和请求2,但是发起请求2时必须依赖于请求1的结果,并且这俩接口还封装在不同的函数,这时我们就可以用async异步函数来处理:
// 模拟请求1
async function ajax1() {
let msg = null;
await new Promise(resolve => {
setTimeout(() => { // 模拟延迟
console.log("第一个请求完毕")
msg = 'hello'; // 模拟赋值
resolve()
}, 1000)
})
return msg
}
// 模拟请求2
async function ajax2(msg) {
console.log(msg)
console.log("第二个请求完毕")
return "my name is weianl"
}
// 运行代码
function run() {
ajax1().then((msg) => {
ajax2(msg).then((data) => {
console.log(data)
})
})
}
run()
好了如果后续出现了async、await、Promise相关,请不要惊慌。
接着我们对比一下直接请求和间接通过云函数请求的区别,以查找数据get()为例子,看下面两段代码你会发现其实两种形式操作数据库的方法是一样的,不同的是引入云函数的方式,小程序端直接请求用wx.
就可以拿到云函数引用了,而云函数间接操作的话需要通过引入wx-server-sdk
来获取。
▲ 小程序端直接操作数据库
const db = wx.cloud.database();
db.collection('集合名').get().then(res => {
console.log(res)
})
▲ 小程序端调用云函数间接操作数据库
/*-------------------云函数代码--------------------*/
// 云函数入口文件
const cloud = require('wx-server-sdk')
//初始云环境,可以填写指定环境
cloud.init()
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
return await db.collection('集合名').get();
}
/*----------------小程序端请求方式------------------*/
wx.cloud.callFunction({
name: '函数名'
}).then(res => {
console.log(res)
})
接着我们来看一下间接云函数操作数据库的一些优势:
接着我们依旧用上面创建的fruit水果集合进行云端的增删改查。
每次修改完云函数记得都要上传至云服务,嫌麻烦的话可以学习一下云函数的本地调试了。
=》在进行本地调试时,需要安装wx-server-sdk,也就是把鼠标放到云函数上面,然后右击选择在外部终端窗口中打开,然后执行命令:
npm install --save wx-server-sdk@latest
=》在云函数中使用 wx-server-sdk
=》云函数本地调试功能
SDK文档-get
在云函数这边查询最高可以一次返回100,再多需要分批次取,例子在上面链接页面的最底部,由于还没有教大家导入数据,我这里就不演示了。
SDK文档-add
SDK文档-remove
SDK文档-update
从GIF中可以看到,不管你这集合设置了什么访问权限,云函数都可以直接绕过它去执行。
除了前面两种操作外,我们还可以通过云开发控制台操作数据库,我用得比较多的是统计集合的总条数,官方给出了很多模板,可以自己尝试一下。
文档:控制台数据库高级操作
导入导出json数据还是比较简单的,需要注意的是最外层不可以用[]
包裹,然后每一条记录后面不可以用,
隔开,然后如果记录里面有数组型对象,那么仍旧需要用,
隔开,具体请看GIF。
.xlsx
表格文件让你导入数据库,那么你需要先把这个文件另存为csv文件,接着把表头的文字改成英文,也就是表格的第一行,英文不好那就拼音拼一下就阔以了,到了这里还是不够的,因为导入的csv只支持utf-8
格式的,所以我们可以先保存为.txt
文件,然后另存为把编码格式改成utf-8
,接着保存后把名字改回.csv
就好了,当然直接按Ctrl+z
也是可以的。如果你不转换编码格式的话,会出现中文乱码的情况,具体请看GIF。,
隔开,并且属性名不可以输错,不然导出的数据会是空的,再者是如果用excel打开csv可能会乱码哦,我同事就遇到过,然后用wps显示就正常,可能是有些版本的excel并不会解码utf-8的csv,注意一些就好了。云存储的话比较简单,现在的api有4中操作能力分别是:上传文件、下载文件、删除文件、换取临时链接。接下来我就不一一示范了,我说一下上传就好了。
从本地相册选择图片或使用相机拍照:wx.chooseImage
云存储文档传送门:API 指引
从GIF我们可以看到上传还是比较简单的,拿来即用就好,不懂的参数查一下文档就好,不过官方的这个代码实例并没有对图片的文件名做处理,并且文件后缀名也被固定了。(另外这里我要提一个坑,一般按理来说我们上传两张同名文件后者是会覆盖前者的,但是我在做一个项目时发现,他喵的,连续上传同名文件两次后用File ID去下载文件时我发现下载下来的还是第一张的,但是我又发现手动刷新页面后再次上传它既然覆盖成功了,喵喵喵?)
所以接下我们可以用时间戳来动态生成图片名,然后用正则表达式来截取你上传时选择的图片的尾缀名,这样重复上传文件后就不会替换掉之前的了,图片类型也动态的换成你上传时的类型了。
const filePath = res.tempFilePaths[0];
console.log('图片临时路径:' + filePath);
const timeStamp = new Date().getTime();
console.log('时间戳:' + timeStamp);
//正则表达式是从官方模板拿的,用于截取你选择的文件尾缀名
const cloudPath = 'myFile/my-image-' + timeStamp + filePath.match(/\.[^.]+?$/)[0];
console.log('自定义文件名:' + cloudPath);
好了,学到这里就算是毕业了。(((┏(; ̄▽ ̄)┛等等,还没装完逼别跑先!!
我们都知道在做前后端分离的项目时,都是后端帮我们整理完图片资源后我们直接通过网络请求来获取。到了小程序云开发的话就有了一种全栈的味道,所以我们得自己上传资源、自己建表、请求出毛病还得自己来检查原因。接下来我写了个简单的小demo,由于博客上传图片不能超过5m,所以我这里就只能快速的带大家过一遍代码了。
File ID
拷过来存到数组记好了,因为小程序的background-image只支持https,所以我们可以用云存储的下载地址
作为url就好了,然后最重要的就是记得改一下集合的访问权限
,因为没有必要通过云函数来拿这一条数据,所以会存在访问权限的问题哦·。具体请看GIF。后续有时间可能会发布的文章
《通过云函数获取用户的微信手机号》==》由于csdn的新规,为了健康和谐的网络环境,所以无法发布了,想要学习的可以私聊
《通过云函数生成带参数的小程序码》
《模糊搜索》
《券码领取,怎么防止用户领取到相同的数据?》
《如何将页面生成为pdf?》
《证件照的实现》
一些不错的学习资源:腾讯课堂-小耿老师、哔哩哔哩-编程小石头、哔哩哔哩-新视觉实训