腾讯犀牛鸟云开发校园技术布道师养成计划第六天


云开发快速入门

如果你想免费、快速的开发出一个完整的项目,用小程序的云开发可能是最好的选择。小程序的云开发所用到的主要是前端开发的知识。

技术文档:云开发官方文档

开通云开发服务

下载Nodejs

NodeJS是在服务端运行JavaScript的运行环境,云开发所使用的服务端环境就是NodeJS。npm是Node包管理器,通过npm,我们可以非常方便的安装云开发所需要的依赖包。

部署并上传云函数

部署并上传云函数

cloudfuntions文件夹图标里有朵小云,表示这就是云函数根目录。展开cloudfunctions,我们可以看到里面有login、openapi、callback、echo文件夹,这些就是云函数目录。而miniprogram文件夹则放置的是小程序的页面文件。

cloudfunctions里放的是云函数,miniprogram放的是小程序的页面,这并不是一成不变的,也就是说你也可以修改这些文件夹的名称,这取决于项目配置文件project.config.json里的如下配置项:

"miniprogramRoot": "miniprogram/",
"cloudfunctionRoot": "cloudfunctions/",

但是你最好是让放小程序页面的文件夹以及放云函数的文件夹处于平级关系且都在项目的根目录下,便于管理。

上传所有云函数

接下来我们按照这样的流程把其他所有云函数(如openapi)都部署都上传,也就是要执行和上面相同的步骤,总结如下:

  1. 右键云函数目录,选择在终端中打开,输入 npm install命令下载依赖文件;
  2. 然后再右键云函数目录,点击“创建并部署:所有文件
  3. 在云开发控制台–云函数–云函数列表查看云函数是否部署成功。

npm包管理器与依赖模块

npm install会下载云函数目录下的配置文件package.json里的dependencies,它表示的是当前云函数需要依赖的模块。package.json在哪里,就在哪里执行npm install,没有package.json,没有dependencies,就没法下载.

执行npm install命令下载的依赖模块会放在node_modules文件夹里,

获取openid与云函数login

当我们把云函数login部署上传成功后,就可以在模拟器以及手机(需要重新点击预览图标并扫描二维码)里点击获取openid了。

点击获取openid

openid是小程序用户的唯一标识,也就是每一个小程序用户都有一个唯一的openid。点击“点击获取openid”,在用户管理指引页面如果显示“用户id获取成功”以及一串字母+数字,那么表示你login云函数部署并上传成功啦。如果获取openid失败,你则需要解决login云函数的部署上传,才能进行下面的步骤哦

调用云函数的解读

技术文档:调用云函数wx.cloud.callFunction

调用云函数的方法很简单,只需要填写云函数的名称name(这里为login),以及需要传递的参数(这里并没有上传参数),就可以进行调用。在success回调函数里添加以下代码打印res对象

再点击“点击获取openid”按钮,就能看到完整的res对象,res对象有三个参数:

  • requestID:云函数执行 ID,可用于在云开发控制台查找日志,打开云开发控制台–云函数–日志,可以在这里根据云函数函数名以及requestID来筛选查看云函数的调用日志(含返回结果);
  • result:**云函数返回的结果**,login云函数返回的结果里包含appid、event对象,我们可以通过res.result.appid以及res.result.event访问它们;
  • errMsg:显示云函数是否调用成功

事件处理函数onGetOpenid调用云函数成功之后,干了三件事情:

  • 使用console.log打印openid,可以在点击按钮触发云函数在控制台看到该打印结果;
  • 把获取到的appid赋值给app.js文件里的globalData全局对象;
  • 跳转到userConsole页面;

保存之后,右键点击index.js文件,选择云函数增量上传:(更新文件),更新login云函数,

打开云开发控制台云函数日志按函数名筛选,选择login云函数,可以看到云函数被调用的日志记录,我们可以在日志里发现:

  • event对象包含程序用户的 openid 和小程序的 appid,而openid就相当于用户的身份证,我们可以根据openid获取到用户的昵称、头像等信息(后面会说明);
  • context对象则是云函数的调用信息和运行状态。
  • 返回结果里我们可以看到return返回的数据

云函数的打印日志会显示在云开发控制台的日志里面,这一点非常重要,要多加利用。只要是打印日志,无论是显示在开发者工具控制台还是显示在云开发控制台的就没有不重要的。

getWXContext()

getWXContext()API是云开发服务端的工具类API,会返回小程序用户的openid、小程序appid、小程序用户的unionid等。说这么多不如直接打印,在下面添加一行打印信息:

const wxContext = cloud.getWXContext()
console.log('getWXContext返回的结果',wxContext)

技术文档:getWXContext()

eturn

return语句是终止函数的执行,并返回一个指定的值给函数调用者

新建云函数

体验上传图片

上传图片到云存储

体验云调用之服务端调用

体验前端操作数据库

前端操作数据库的页面逻辑

以上的函数是在小程序的前端页面来操作数据库,点击开发者工具模拟器云开发QuickStart里的前端操作数据库,

  • 在第1步(数据库指引有标注),我们会获取到用户的openid,也就是说你没有获取到openid是没法通过小程序的前端来操作数据库的哦
  • 第2步,需要我们在云开发控制台里的数据库管理页创建一个counters的集合(不需添加数据);
  • 第3步,点击按钮页面的按钮“新增记录”(按钮就在这个页面的第4条与第5条之间,看起来不是那么明显),这时会调用 onAdd方法,往counters集合新增一个记录(之前手动添加有木有很辛苦?),我们可以去云开发控制台的数据库管理页查看一下counters集合是不是有了一条记录;大家可以多点击几下新增记录按钮,然后去云开发控制台看数据库又有什么变化。也就是小程序前端页面通过 onAdd方法,在数据库新增了记录。
  • 第4步,点击按钮查询记录,这时调用的是 onQuery方法就能在小程序里获取到第3步我们存储到数据库里的数据啦
  • 第5步,点击计数器按钮+号和-号,可以更新count的值,点击+号按钮会调用 onCounterInc方法,而点击-号 onCounterDec方法,比如我们点击加号到7,再去数据库管理页查看最新的一条记录(也就是最后一条),它的count由原来的1更新到了7(先点刷新按钮),我们再点击-号按钮到5,再来数据库管理页查看有什么变化变化(先点刷新按钮
  • 第6步,点击删除记录按钮,会调用 onRemove方法,这时会删掉数据库里最新的记录(也就是第5步里的那一条记录)。

通过实战我们了解到,databaseGuide.js文件里的 onAdd、 onQuery、 onCounterInc、 onCounterDec、 onRemove可以实现小程序的前端页面来操作数据库。

在前面JavaScript的章节里我们了解到数据以及数据的存储是非常重要的,而有了数据库,用函数生成的数据能够比缓存存储的更加持久,而且在上面我们实现了对数据进行增(添加)、删(删除)、改(修改、更新)、查(查询并渲染到页面),不仅如此,缓存的容量也比较有限,最多不过10M,而数据库可以存几百G以上,可见它的重要性。

当新建了并配置了云函数根目录为cloudfunctions文件夹之后,云函数根目录里并没有云函数,我们可以右键点击云函数根目录cloudfunctions文件夹选择同步云函数列表,可以把所有云端的云函数列表都列举出来(这只是列举了列表),而要修改云函数里面的内容,我们可以右键点击其中的一个云函数目录选择下载云函数即可。

除此之外,我们需要小程序的app.js的生命周期函数onLaunch里使用wx.cloud.init()来初始化云开发能力:

onLaunch: function () {
  if (!wx.cloud) {
    console.error('请使用 2.2.3 或以上的基础库以使用云能力')
  } else {
    wx.cloud.init({
      env: '你的环境ID',
      traceUser: true,
    })
  }
},

云开发能力全局只需要初始化一次即可,这里的traceUser属性设置为true,会将用户访问记录到用户管理中,在云开发控制台的运营分析用户访问里可以看到访问记录。

基础库与wx.cloud

CloudID: ƒ () //用于云调用获取开放数据
callFunction: ƒ () //调用云函数
database: ƒ () //获取数据库的引用
deleteFile: ƒ () //从云存储空间删除文件
downloadFile: ƒ () //从云存储空间下载文件
getTempFileURL: ƒ () //用云文件 ID 换取真实链接
init: ƒ ()  //初始化云开发能力
uploadFile: ƒ () //上传文件至云存储空间

云开发能力

通过云开发的能力进行调用云函数、上传图片、操作数据库以及使用小程序的一些开放接口,下面来进一步了解和使用云开发能力,并加强对云端测试本地调试以及本地Console日志打印云端日志打印的理解。

本地调试与云端测试

第一步:新建云函数

第二步:本地调试云函数是否正确

第三步:云端测试云函数是否正确

小程序端与服务端

小程序端与云端的初始化

小程序默认可以创建两个环境,这两个环境都有云函数配置、数据库、云存储且独立隔离,开发上会存在两个环境切换的情况(一个用于生产环境,一个用于测试环境),而区别这两个环境的就是它们的环境ID,小程序端与云端的初始化时要注意。

云函数中的API调用的环境也可以使用初始化来设置。

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
})

cloud.DYNAMIC_CURRENT_ENV设置 API 默认环境等于当前所在环境建议所有的云函数都使用以上方式来初始化,也就是配置env的值为cloud.DYNAMIC_CURRENT_ENV或使用你的环境ID,不要为空**。

关于wx-server-sdk

每一个云函数都会用到wx-server-sdk这个Node包,而要使用这个包都需要有Nodejs环境,小程序端的本地需要我们自己下载Nodejs(前面已下载),而云端则自带Nodejs环境。

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标签查看调用云函数的情况。

获取用户信息和登录

使用open-type=”getUserInfo” 来获取用户信息的作用和 wx.getUserInfo API基本效果是一样的,区别在于wx.getUserInfo 这种方式最好是在用户允许获取公开信息(也就是res.authSetting[‘scope.userInfo’]的值为true)之后再调用,如果用户拒绝了授权就不会再有弹窗(除非用户删掉了你的小程序再使用),调用就会失败,而使用组件的方式是用户主动点击,用户即使拒绝了,再点击仍会弹出授权弹窗。所以推荐先使用组件来获取用户授权,然后再来使用wx.getUserInfo来获取用户信息。

通过button获取用户信息

获取用户高清头像

我们发现获取到的头像不是很清晰,这是因为默认的头像大小为132132(UserInfo用户头像说明),如果把avatarUrl链接后面的132修改为0就能获取到640640大小的头像了:

页面加载时就显示用户信息

openid、用户信息与登录

尽管我们已经获取到了用户的头像、昵称等信息,但是这不能称之为真正意义的登录,只有获取到了用户身份的唯一ID也就是openid,我们才能把用户行为比如点赞、评论、发布文章、收藏等与用户挂钩,用户这些行为都与数据库有关,而能够确定点赞、评论、文章、收藏这些数据与用户关系的就是openid,也就是说只要获取到了openid就意味着用户已经登录,而获取用户信息(如头像、昵称)不过是一个附加服务,这两个是可以完全独立的。没有openid,我们也无法把用户信息给存储到数据库,也就没法让用户自定义用户信息。无论是用户行为,还是用户的信息,openid都是一个重要的桥梁。

通过前面的login云函数,我们就已经可以获取到用户的openid。无需维护复杂的鉴权机制,即可获取天然可信任的用户登录态(openid),是云开发的一个重要优势。无论是云存储还是云数据库,openid都扮演着一个重要的角色。

小程序端上传图片到云存储

要把图片上传到云存储,会使用到wx.cloud.uploadFile,这个API是小程序端的API,它是把本地资源也就是临时文件里的文件上传到云存储里。在前面《图片、缓存与文件》章节里我们已经了解到如何把图片上传到小程序的临时文件,而要把临时文件上传到云存储,则需要调用wx.cloud.uploadFile API。

技术文档:wx.cloud.uploadFile

在wx.cloud.uploadFile技术文档里,可以看到要调用API,需要获取图片的filePath,在小程序里为临时文件的路径,也就是要把上传到小程序的临时文件路径赋值给它;还有一个cloudPath,这个为文件的云存储路径,这个是我们可以任意设置的

文件名与后缀的处理

我们知道一个文件由文件名称文件后缀构成,比如tcb.jpg和cloudbase.png,jpeg说明图片的格式是JPG格式,而png说明图片是PNG格式,文件名称相同格式相同就是出现覆盖,如果我们随意更改了文件的后缀,大多数文件就会打不开。所以要把cloudPath云存储的路径需要我们把文件名和后缀给处理好。

const cloudPath = `${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]

给文件名加上时间戳和一个随机数,时间戳是以毫秒计算,而随机数是以1000内的正整数,除非1秒钟(1秒=1000毫秒)上传几十万张照片,不然文件名是不会重复的。

上传图片到云存储是无法直接获取到图片的下载地址的

云存储的二级目录

渲染云存储图片到组件

在云开发控制台的存储里,我们可以看到每张图片的详细信息都有上传者 Open ID,无论你是使用开发者工具在模拟器的小程序里上传还是预览在手机的小程序里上传,只要你用的是同一个微信账号,这个上传者openid都是一致的,云存储会自动记录上传者的openid

云函数上传图片到云存储

云开发不仅在小程序端可以上传文件到云存储,还可以通过云函数也就是云端上传图片到云存储(这里会涉及到一点Nodejs的知识)。

技术文档:uploadFile

注意云函数上传图片的API属于服务端API,与wx.cloud.uploadFile是小程序端API不同

由于云端测试无法获取用户登陆态信息,所以我们不能在云端测试里把图片上传到云存储,需要在小程序端调用,使用开发者工具在login.wxml输入以下代码,也就是新建一个绑定uploadimg事件处理函数的button用于触发:

注意,通过这种方式上传到云存储的图片,是没有上传者 Open ID的,在云存储里查看这张图片的详细信息,就可以了解到。

调用数据库

数据库的导入

打开云开发控制台,在数据库里新建一个集合zhihu_daily,导入该json文件,导入时会有冲突模式选择,看下面的介绍,推荐大家使用upsert:

  • Insert:总是插入新记录
  • Upsert:如果记录存在则更新,否则插入新记录

导入后,发现数据库自动给每一条数据(记录)都加了唯一的标识_id

小程序端调用数据库

在小程序端调用数据库的方式很简单,我们可以把下面的代码写到一个事件处理函数里,然后点击组件触发事件处理函数来调用;也可以直接写到页面的生命周期函数里面;还可以把它写到app.js小程序的生命周期函数里面。

使用开发者工具,将下面的代码写到login.js的onLoad函数里面,我们

  • 先使用wx.cloud.database()**获取数据库**的引用(相当于连接数据库);
  • 再使用**db.collection()**获取集合的引用;
  • 再通过Collection.get来获取集合里的记录.
const db = wx.cloud.database()
db.collection('zhihu_daily')
  .get()
  .then(res => {
    console.log(res.data)
  })
  .catch(err => {
    console.error(err)
  })

如果没有指定 limit,则默认最多取 20 条记录

云函数调用数据库

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()
}

openid与数据库

在云开发控制台的数据库标签里,打开上一节内容里的counters集合,在这个集合里我们可以看到每条记录除了有_id字段以外,还有一个_openid字段用来标志每条记录的创建者(也就是小程序的用户)。

我们可以自定义 _id(也就是给数据添加一个_id字段并填入任意值),但不可自定义和修改 _openid 。 _openid 是在文档创建时由系统根据小程序用户默认创建的,可以用来标识和定位文档。和云存储一样,数据库的记录也和openid有着紧密的联系。

2020-03-24 12-26-54屏幕截图.png


文章作者: 毛雷
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 毛雷 !
评论
  目录