微信小程序云开发入门
第一部分:云开发介绍
快速了解微信云开发
云开发
采用全新的serverless开发模式,涵盖云函数、数据库、CDN、存储和云调用能力,提供完整的一站式后端云服务。
就是腾讯云把后端服务都搭好了,云函数就就相当于后端的接口,前端页面调用云函数操作数据库,存储的文件直接进cdn。
变化
对前端工程师来说不光要写页面,对接口还要写接口。对前端工程师来说工作量变大了。
对老板来说,整个项目周期缩短了,成员变少了,成本降低了。
疑问
云开发只能用腾讯云一家厂商,项目做大之后又遇上腾讯云提价,项目迁移起来就很难了,如果想迁移到常规服务器就要考虑很多云开发可以直接忽略的问题(微信鉴权),云开发的数据库(JSON格式),cdn存储都不好迁移。
云开发是什么
什么是云开发
云开发是微信团队联合腾讯云提供的原生Serverless云服务,致力于帮助更多开发者快速实现小程序业务的开发,快速迭代。
云开发与传统模式的对比
传统模式:
云开发:
对比:
云开发能力介绍
存储:在小程序端直接上传/下载云端文件,可视化管理
云函数:在云端运行的代码,微信私有天然鉴权,开发者只需编写自身业务逻辑代码
云数据库:一个既可在小程序前端操作,也能在云函数中读写的JSON数据库
音视频服务:提供互通高品质实时音频通话服务,支持互动白板,美颜滤镜,高清视频通话,基于云开发快速接入
智能图像服务:集成智能鉴黄、人脸识别、人脸核身等AI视觉能力,基于云开发快速接入
云开发对小程序的变革
一天一交付,一天多交付成为可能:云开发的模式可以帮助开发者快速迭代产品,一天多次产品交付成为可能。
小团队也可以做大事情:云开发的模式简单易懂,小团队也可以借助云计算的能力,做一些更大的事情。
弹性成本几乎为0:所有资源都由服务方来管理,团队只需要关注业务逻辑
云开发基本功能演示
云开发的数据存储能力
云开发为小程序开发者提供了数据存储能力,帮助开发者快速完成应用的开发。
传统的数据存储模式
云开发的数据存储模式
一行代码创建数据
db.collection('表名').add({ data: { 字段1:'数据1', 字段2:'数据2' }, success(res){ console.log(res) } })
一行代码查询数据
db.collection('表名').doc('记录ID').get({
success(res){
console.log(res.data)
}
})
云开发的计算能力
云开发为小程序开发者提供了开箱即用的计算平台,开发者只需关注自己的核心逻辑,就可以完成复杂逻辑的编写
传统模式下的计算能力的实现
云开发模式下的计算能力的实现
云开发的文件存储能力
云开发为小程序开发者提供了配置好常用环境的海量非结构化数据存储,帮助开发者解决数据存储的问题。
演示:第一个云开发小程序
可在云开发控制台查看调用云函数日志
云开发控制面板介绍
如何进入云开发控制台
云开发控制台的几个功能
概览:数据统计
运营分析:资源使用、用户访问、监控图表:数据统计
数据库:
存储
云函数
云开发 API 简介
第二部分:云开发快速入门体验
云开发快速入门
https://developers.weixin.qq.com/community/business/doc/000e26815e8de0db1ecae5a035b00d
笔记:
1、
指定小程序的云开发环境
在开发者工具中打开源代码文件夹 miniprogram 里的 app.js,找到如下代码:
wx.cloud.init({
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
env: 'my-env-id',
traceUser: true,
})
在 env: 'my-env-id'处改成你的环境 ID,如 env: 'xly-snoop'
2、
cloudfunctions里放的是云函数,miniprogram放的是小程序的页面,这并不是一成不变的,也就是说你也可以修改这些文件夹的名称,这取决于项目配置文件project.config.json里的如下配置项:
"miniprogramRoot": "miniprogram/",
"cloudfunctionRoot": "cloudfunctions/",
但是你最好是让放小程序页面的文件夹以及放云函数的文件夹处于平级关系且都在项目的根目录下,便于管理。
3、
getWXContext()
getWXContext()API 是云开发服务端的工具类 API,会返回小程序用户的 openid、小程序 appid、小程序用户的 unionid 等。说这么多不如直接打印,在下面添加一行打印信息:
const wxContext = cloud.getWXContext()
console.log('getWXContext返回的结果',wxContext)
4、
组件支持
我们可以把下载地址作为图床来使用的,也就是你可以把图片的下载地址放到其他网页图片是可以显示的。云存储的图片还有一个 FileID(既云文件 ID,以 cloud://开头)则只能用于小程序的特定场景,也只有部分组件的部分属性支持,把链接粘贴到浏览器也是打不开的。
5、
基础库与 wx.cloud
在小程序端初始化云开发能力的代码里,涉及到 wx.cloud 以及基础库版本的知识。关于 wx.cloud,我们可以和之前在控制台了解 wx 对象一样,直接在开发者工具的控制台里输入:
wx.cloud
来了解对象有哪些属性与方法。我们可以看到有如下方法:
CloudID: ƒ () //用于云调用获取开放数据
callFunction: ƒ () //调用云函数
database: ƒ () //获取数据库的引用
deleteFile: ƒ () //从云存储空间删除文件
downloadFile: ƒ () //从云存储空间下载文件
getTempFileURL: ƒ () //用云文件 ID 换取真实链接
init: ƒ () //初始化云开发能力
uploadFile: ƒ () //上传文件至云存储空间
而关于基础库,有三个地方需要注意它的存在,平时开发的时候需要留意开发者工具的project.config.json里有这样一个属性libVersion,这个也可以在开发者工具工具栏右上角的详情里的本地设置里的调试基础库,建议切换到最新,切换后libVersion的值也会修改到切换的版本;
官方文档基础库的更新日志,小程序更新非常频繁,而更新的核心就是基础库:所以基础库更新日志要经常留意每个API,技术文档都会标明它的基础库支持的最低版本,而小程序·云开发 SDK是2.2.3以上的基础库才开始支持的。
云函数中的 API 调用的环境也可以使用初始化来设置。
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
cloud.DYNAMIC_CURRENT_ENV 设置 API 默认环境等于当前所在环境。建议所有的云函数都使用以上方式来初始化,也就是配置 env 的值为 cloud.DYNAMIC_CURRENT_ENV 或使用你的环境 ID,不要为空。
2、
async 与 await
在 wx-server-sdk 中不再兼容 success、fail、complete 回调,只会返回 Promise。在云函数中也经常会需要处理一些异步操作,在异步操作完成后再返回结果给到调用方,我们可以通过在云函数中返回一个 Promise 的方法来实现。Promise 表示异步操作返回的结果。在新建的云函数里会看到下面这样的一个语句(有 async):
exports.main = async (event, context) => {
}
async 表示函数里有异步操作,async 函数的返回值是一个 Promise 对象。在后面还会遇到 await,表示紧跟在它后面的表达式需要等待结果;以及 promise 对象的 then()方法(有点类似于 success 回调函数),和 catch()方法(有点类似于 fail 回调函数),这些我们以后会经常遇到,先理解不了也没有关系,大家在书写时推荐云函数使用上面的写法就对了。
云函数的注意事项
在云函数部署并上传到云端之后,更新里面的文件比如index.js、config.json,建议右键点击更新好的文件(不是云函数目录)选择云函数增量上传:更新文件,不建议通过上传并部署所有文件的方式,否则在几分钟内会出现云函数调用失败的情况;
删除一个云函数之后,不建议再新建一个同名的云函数并上传部署,否则在十多分钟内会出现云函数调用失败的情况,建议换一个云函数名,比如login换成user,在小程序端使用 wx.cloud.callFunction({name: ''})调用云函数时把name的值换成user就可以了
调用云函数时,我们还可以在开发者工具调试面板的NetWork标签查看调用云函数的情况。
3、
获取用户高清头像
我们发现获取到的头像不是很清晰,这是因为默认的头像大小为 132132(UserInfo 用户头像说明),如果把 avatarUrl 链接后面的 132 修改为 0 就能获取到 640640 大小的头像了:
getUserInfomation: function (event) {
let { avatarUrl, city, nickName}= event.detail.userInfo
avatarUrl = avatarUrl.split("/")
avatarUrl[avatarUrl.length - 1] = 0;
avatarUrl = avatarUrl.join('/');
this.setData({
avatarUrl,city, nickName
})
},
4、
页面加载时就显示用户信息
在获得了用户授权和用户信息的情况下,刷新页面或进行页面跳转,用户的个人信息还是不会显示,这是因为 getUserInfomation 事件处理函数点击组件时才触发,我们需要在页面加载时也能触发获取用户信息才行。
我们可以在 login.js 的 onLoad 生命周期函数里输入以下代码,当用户授权之后来调用 wx.getUserInfo() API:
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
wx.getUserInfo({
success: res => {
let { avatarUrl, city, nickName } =res.userInfo
this.setData({
avatarUrl, city, nickName
})
}
})
}
}
});
这样当我们加载页面时,用户的信息就能显示出来了,不过这里的头像是从 API 里重新取的,也会不清晰。我们当然可以像之前一样把头像的链接替换一下,但是如果每个页面都这么写就会很麻烦,解决的方法有 2 种,一种是把高清头像存储到缓存里,还有一种是把代码封装成一个组件(大家可以自己研究如何自定义组件了)。
5、
云存储的二级目录
在存储里我们都是把所有的图片放在根目录下,没有二级目录,那我们能不能建一个二级目录呢?当然是可以的,我们可以在 cloudPath 的前面加一个文件路径就可以了,比如:
const cloudPath = `cloudbase/${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]
云函数调用数据库
使用云函数也可以调用数据库,使用开发者工具右键点击云函数根目录也就是 cloudfunctions 文件夹,选择新建 Node.js 云函数,云函数的名称命名为 zhihu_daily,然后打开 index.js,输入以下代码:
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()
exports.main = async (event, context) => {
return await db.collection('zhihu_daily')
.get()
}
第三部分:数据库基础能力介绍
数据库权限管理
云开发控制台内修改数据库权限
正则表达式
地理位置查询
数组查询
字段类型查询
没有该字段的记录会只显示ID
第四部分:存储基础能力介绍
1 云开发基础能力展示·文件存储
2 云开发基础能力展示·生成临时链接
第五部分:云函数基础能力介绍
在云函数中查询数据
云开发基础能力展示 - 云函数定时器的使用
演示
1、新建云函数
2、index.js中随便打印点什么,右键新建的云函数目录点击 上传并部署:云端安装依赖(......)
3、config.json配置触发器参数,右键config.json 上传触发器
4、查看日志,会发现隔几秒就会产生一个日志(记录日志会消耗时间)
第六部分:云开发进阶学习
笔记:
1、
云函数目录里的 config.json 文件可以用来配置权限和定时触发器,如果你的云函数目录下面没有这个配置文件,可以自己创建一个,创建的结构目录如下:
test //云函数目录
├── config.json //权限和定时触发器等的配置文件
├── index.js //云函数
├── package.json //云函数的依赖管理
2、Cron 表达式语法
Cron 表达式有七个必填字段,按空格分隔,既不能多写也不能少写,每一个字段都有它的含义对应着不同的时间点,表达式的取值都为整数且为时间制的范围(注意月在星期的前面):
第一位第二位第三位第四位第五位第六位第七位秒(0-59 )分钟(0-59)小时(0-23)日(1-31)月(1-12或三个字母的英文缩写)星期(0-6或三个字母的英文缩写)年(1970~2099 )
下面是 cron 表达式的案例,以及我们需要了解一下 cron 表达式里的通配符以及直接写数字的含义:
,
,表示并集,在时间的表述里是“和”的意思,比如在“小时”字段中,1,2,3
表示 1 点、2 点和 3 点;-
,指定范围的所有值,在时间的表述里是“到”的意思,比如在“日”字段中,1-15
包含指定月份的 1 号到 15 号;*
,表示所有值,在时间的表述里是“每”的意思,比如在“小时”字段中,*
表示每小时;/
,指定步长,在时间的表述里是“隔”的意思,比如在“秒”字段中,*/5
表示每隔 5 秒;- 直接写数字,在时间的表述里是“第”(时间点)的意思,比如在“月”字段中,
5
表示每月的第 5 日;
//表示每隔5秒触发一次,
*/5 * * * * * *
//表示在每月的1日的凌晨2点触发
0 0 2 1 * * *
//表示在周一到周五每天上午10:15触发
0 15 10 * * MON-FRI *
//表示在每天上午10点,下午2点,4点触发
0 0 10,14,16 * * * *
//表示在每天上午9点到下午5点内每半小时触发
0 */30 9-17 * * * *
//表示在每个星期三中午12点触发
0 0 12 * * WED *
定时触发器的 Cron 语法没法实现每隔 90 秒钟或 90 分钟发送一次这样的效果,因为 90 秒超过了秒的时间制上限 60,而 cron 在跨位组合(比如 90 秒需要结合秒和分)上无法覆盖所有的时间;除此之外,云开发的触发器暂时不支持多个定时触发器的叠加;在 Cron 表达式中的“日”和“星期”字段同时指定值时,两者为“或”的关系,即两者的条件均生效;值得一提的是,尽管云函数的时区为 UTC+0 时区,但是定时触发器的时间还是北京时间。
云开发基础Node.js
1、
Nodejs 的内置模块
在前面我们已经接触过 Nodejs 的 fs 模块、path 模块,这些我们称之为 Nodejs 的内置模块,内置模块不需要我们使用 npm install 下载,就可以直接使用 require 引入:
const fs = require('fs')
const path = require('path')
Nodejs 的常用内置模块以及功能如下所示,这些模块都是可以在云函数里直接使用的:
- fs 模块:文件目录的创建、删除、查询以及文件的读取和写入,下面的 createReadStream 方法类似于读取文件,
- path 模块:提供了一些用于处理文件路径的 API
- url 模块:用于处理与解析 URL
- http 模块:用于创建一个能够处理和响应 http 响应的服务
- querystring 模块:解析查询字符串
- until 模块 :提供用于解析和格式化 URL 查询字符串的实用工具;
- net 模块:用于创建基于流的 TCP 或 IPC 的服务器
- crypto 模块:提供加密功能,包括对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装
在云函数中使用 HTTP 请求访问第三方服务可以不受域名限制,即不需要像小程序端一样,要将域名添加到 request 合法域名里;也不受 http 和 https 的限制,没有域名只有 IP 都是可以的,所以云函数可以应用的场景非常多,即能方便的调用第三方服务,也能够充当一个功能复杂的完整应用的后端。不过需要注意的是,云函数是部署在云端,有些局域网等终端通信的业务只能在小程序里进行。
常用变量
module、exports、require
Lodash 实用工具库
moment 时间处理
获取公网 IP
Buffer 文件流
图像处理 sharp
连接数据库 MySQL
二维码 qrcode
邮件处理
Excel 文档处理
HTTP 处理
加解密 Crypto
发短信
云开发实时数据推送讲解
https://developers.weixin.qq.com/community/business/doc/000860c44d0a881d17ca2d02c5100d
2、实时数据推送注意事项
01实时数据推送只支持小程序端(Web 端)
实时数据推送的 watch 请求只支持在小程序端(Web 端)等前端调用,不支持云函数端。
云开发安全规则讲解
https://developers.weixin.qq.com/community/business/doc/000eaa8ba2c9482d16ca7dab456c0d
1、查询写入都需明确指定 openid
2、doc 操作需转为 where 操作
3、嵌套数组对象里的 openid
在使用简易权限配置时,用户在小程序端往数据库里写入数据时,都会给记录 doc 里添加一个_openid 的字段来记录用户的 openid,使用安全规则之后同样也是如此。在创建记录时,可以把{openid}变量赋值给非_openid 的字段或者写入到嵌套数组里,后台写入记录时发现该字符串时会自动替换为小程序用户的 openid:
db.collection("posts").add({
data: {
books: [
{
title: "云开发快速入门",
author: "{openid}",
},
{
title: "数据库入门与实战",
author: "{openid}",
},
],
},
});
以往要进行 openid 的写入操作时需要先通过云函数返回用户 openid,使用安全规则之后,直接使用{openid}变量即可,不过该方法仅支持 add 添加一条记录时,不支持 update 的方式。