小程序|云开发能力基础讲解

云开发能力基础讲解

阅读最新文档点击进入官方文档学习,也可以直接阅读参考本文笔记,因为这里包括一些代码错误和确实的地方补齐。

本地调试与云端测试

本地调试

右键点击云函数目录,也就是 rectangle 文件夹,选择本地调试(这种方式进入本地调试会默认开启 rectangle 的本地调试)。

注意:这步骤以后注意是本地调试界面右侧的【调试方式】要选择【手动触发】,否则会找不到输入 mock data 的地方。

在这里插入图片描述

还有一个本地调试入口,是IDE中【云开发】按钮,进去后的【云函数】中的【云函数列表】Tab页,会有【本地调试】还是【云端调试】。

小程序端与服务端

小程序端与云端的初始化

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 环境。那这个 wx-server-sdk 到底什么呢?我们可以打开它的 npm 包地址:

npm 包地址:wx-server-sdk 包地址

在 Dependencies 标签页可以看到 wx-server-sdk 依赖 tcb-admin-node、protobufjs、tslib 这三个包,而其中 tcb-admin-node 是核心,学有余力的童鞋可以看一下它的技术文档。

技术文档:tcb-admin-node 的 Github 地址

async 与 await

云函数的注意事项

    在云函数部署并上传到云端之后,更新里面的文件比如index.js、config.json,建议右键点击更新好的文件(不是云函数目录)选择云函数增量上传:更新文件,不建议通过上传并部署所有文件的方式,否则在几分钟内会出现云函数调用失败的情况;
    删除一个云函数之后,不建议再新建一个同名的云函数并上传部署,否则在十多分钟内会出现云函数调用失败的情况,建议换一个云函数名,比如login换成user,在小程序端使用 wx.cloud.callFunction({name: ''})调用云函数时把name的值换成user就可以了
    调用云函数时,我们还可以在开发者工具调试面板的NetWork标签查看调用云函数的情况。

获取用户信息和登录

划重点:推荐先使用组件来获取用户授权,然后再来使用wx.getUserInfo来获取用户信息。

通过 button 获取用户信息

使用开发者工具新建一个 login 页面,然后在 login.wxml 里输入以下代码,我们通过组件的方式来获取用户的信息:1

  <view>
    <button open-type="getUserInfo" bindgetuserinfo="getUserInfomation">点击获取用户信息</button>
    <view>
      <image src="{{avatarUrl}}" />
      <view>{{city}}</view>
      <view>{{nickName}}</view>
    </view>
  </view>

在 login.js 的 data 里初始化 avatarUrl、nickName 以及 city,没有获取到用户信息时,用一张默认图片代替,昵称显示用户未登录,city 显示为未知:

  data: {
    avatarUrl: '/images/user-unlogin.png',
    nickName:"用户未登陆",
    city:"未知",
  },

然后在 login.js 文件里输入以下代码,在事件处理函数 getUserInfomation 我们可以打印 event 对象,open-type=”getUserInfo”的组件的 event 对象的 detail 里就有 userInfo:

  getUserInfomation(event) {
    let { avatarUrl, city, nickName } = event.detail.userInfo
    this.setData({
      avatarUrl,
      city,
      nickName
    })
  },

将获取的 avatarUrl,city,nickName 通过 this.setData()赋值给 data。编译之后点击点击获取用户信息按钮,首先会弹出授权弹窗,当用户确认之后,就会显示用户的信息。

event.detail.userInfo 的字段包括:nickName, gender, language, city, province, country 以及 avatarUrl。

获取用户高清头像

我们发现获取到的头像不是很清晰,这是因为默认的头像大小为 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
    })
  },

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

在获得了用户授权和用户信息的情况下,刷新页面或进行页面跳转,用户的个人信息还是不会显示,这是因为 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 种,一种是把高清头像存储到缓存里,还有一种是把代码封装成一个组件(大家可以自己研究如何自定义组件了)。

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,这个为文件的云存储路径,这个是我们可以任意设置的。

使用开发者工具在 login.wxml 里添加以下代码,代码和前面章节基本一致,大家也可以回顾一下以前的内容:1

<button bindtap="chooseImg">点击选择图片</button>
<image src="{{imgurl}}" />

然后在 login.js 的 data 里初始化 imgurl,这里 imgurl 是一个字符串,

  data: {
    imgurl: "",
  },

然后在 login.js 里添加事件处理函数 chooseImg,我们再来回顾一下临时文件的知识:

  chooseImg: function () {
    wx.chooseImage({
      count: 1,
      sizeType: ['compressed'],
      sourceType: ['album', 'camera'],
      success: function (res) {
        console.log(res)
        console.log(res.tempFilePaths)
      }
    })
  },

编译后,上传一张图片,在控制台里我们可以看到 res.tempFilePaths 是一个数组格式,而 wx.cloud.uploadFile 的 filePath 是一个字符串,所以我们在上传时,可以把第一张图片的路径(字符串)赋值给 filePath:

const filePath = res.tempFilePaths[0]

文件名与后缀的处理

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

当我们把图片上传到小程序的临时文件后,我们可以查看一下临时路径是什么样子的:

http://tmp/wx7124afdb64d578f5.o6zAJs291xB-a5G1FlXwylqTqNQ4.esN9ygu5Hmyfccd41d052e20322e6f3469de87f662a0.png

临时路径的文件名就不是原来的文件名,会变成一段长字符,但文件的格式还是原来的文件格式(后缀)。那 cloudPath 要输入文件的路径,就需要填写文件名和文件格式,这个要怎么处理呢?

在上一节的 QuickStart 小程序里,文件上传到云存储的处理方式如下:

const cloudPath = 'my-image' + filePath.match(/\.[^.]+?$/)[0]

也就是它把上传的所有图片都命名为 my-image,而文件的后缀还是原来的文件后缀(也就是文件格式不变)。这里的 filePath.match(/.[^.]+?$/)[0]是字符串的正则处理,后面我们会来详细了解。我们先可以在开发者工具的控制台输入以下代码了解一下它的功能:

const filepath="http://tmp/wx7124afdb64d578f5.o6zAJs291xB-a5G1FlXwylqTqNQ4.esN9ygu5Hmyfccd41d052e20322e6f3469de87f662a0.png"
filepath.match(/\.[^.]+?$/)[0]

打印可以得到临时文件的后缀,这里为.png。这种把所有文件都命名为 my-image 的做法,会导致当文件的后缀相同时文件会被覆盖,如果不希望文件被覆盖,我们需要给文件命不同的名字,我们可以这样处理:

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

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

结合上面的内容,我们可以把 wx.chooseImage()的 success 回调函数如下处理:

success: function (res) {
  const filePath = res.tempFilePaths[0]
  const cloudPath = `${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]
  wx.cloud.uploadFile({
    cloudPath,
    filePath,
    success: res => {
      console.log('上传成功后获得的res:', res)
    },
  })
}

编译之后,我们再次上传一张图片就会打印上传成功之后的 res 对象,里面包含图片在云存储里的 fileID,注意它的文件名和文件后缀,以及我们可以在云开发控制台的存储里找到你上传的图片,也就是说我们上传图片到云存储是无法直接获取到图片的下载地址的。

云存储的二级目录

在存储里我们都是把所有的图片放在根目录下,没有二级目录,那我们能不能建一个二级目录呢?当然是可以的,我们可以在 cloudPath 的前面加一个文件路径就可以了,比如:

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

渲染云存储图片到组件

在上一节组件支持部分了解到,我们是可以把 fileID 直接在小程序的某些组件里渲染出来的。综合以上内容 chooseImg 事件处理函数最终为以下代码(注意 this.setData 的 this 指向,这里为了方便把 success 回调都写成了箭头函数):

  chooseImg: function () {
    wx.chooseImage({
      count: 1,
      sizeType: ['compressed'],
      sourceType: ['album', 'camera'],
      success: res => {
        const filePath = res.tempFilePaths[0]
        const cloudPath = `cloudbase/${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]
        wx.cloud.uploadFile({
          cloudPath,
          filePath,
          success: res => {
            console.log('上传成功后获得的res:', res)
            const imgurl=res.fileID
            this.setData({
              imgurl
            })
          },
        })
      }
    })
  },
在云开发控制台的存储里,我们可以看到每张图片的详细信息都有上传者 Open ID,无论你是使用开发者工具在模拟器的小程序里上传还是预览在手机的小程序里上传,只要你用的是同一个微信账号,这个上传者openid都是一致的,云存储会自动记录上传者的openid。

小任务:结合《图片、缓存与文件》章节里的wx.chooseMessageFile()的知识,将客户端会话(微信聊天窗口)里的视频、音频、PDF、Excel 等也上传到云存储里。

云函数上传图片到云存储

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

技术文档:uploadFile

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

使用开发者工具右键点击云函数根目录也就是 cloudfunctions 文件夹,选择新建 Node.js 云函数,云函数的名称命名为 uploadimg,右键点击 uploadimg 文件夹,选择硬盘打开,然后拷贝一张图片如 demo.jpg 进去,文件结构如下:

uploadimg云函数目录
├── index.js
├── package.json
├── demo.jpg

然后打开 index.js,输入以下代码:

const cloud = require('wx-server-sdk')
const fs = require('fs')
const path = require('path')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
  const fileStream = fs.createReadStream(path.join(__dirname, 'demo.jpg'))
  return await cloud.uploadFile({
    cloudPath: 'tcbdemo.jpg',
    fileContent: fileStream,
  })
}

然后右键点击 uploadimg 文件夹,选择在终端中打开,输入 npm install 安装依赖,再点击 uploadimg 文件夹,选择上传并部署所有文件(这时图片也一并上传到了云端)。

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

<button bindtap="uploadimg">点击上传图片</button>

然后在 login.js 里输入以下代码,在事件处理函数 uploadimg 里调用 uploadimg 云函数,并返回调用之后的 res 对象:

  uploadimg() {
    wx.cloud.callFunction({
      name: 'uploadimg',
      success: res => {
        console.log(res)
      }
    })
  },

编译之后,点击云函数上传图片按钮,就可以调用 uploadimg 云函数,从而调用 uploadFile API 将服务端/云端的图片上传到云存储里面啦,可以打开云开发控制台的云存储查看是否有 tcbdemo.jpg 这张图片。

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

调用数据库

数据库的导入

在调用数据库之前,我们需要先有一个比较贴近实际的数据库案例,为此把前面章节用到的知乎日报数据整理出了一个数据库文件。云开发数据库支持用文件的方式导入已有的数据(这里推荐大家使用 json)。

数据库下载:知乎日报文章数据

右键点击链接,将 data.json 存储到电脑。为了方便大家阅读与编辑 data.json 文件的内容,推荐大家使用 Visual Studio Code 编辑器。

代码编辑器:Visual Studio Code

编辑器的汉化与插件:可能你安装的VS Code的界面是英文的,可以参照VSCode设置中文显示,将VS Code汉化。

使用 VS Code 编辑器打开 data.json,发现数据的内容与写法我们都比较熟悉,知识各个记录对象之间是使用回车 \n 分隔,而不是逗号,这一点需要大家注意。

打开云开发控制台,在数据库里新建一个集合 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)
  })

编译之后,就能在控制台看到调用的 20 条数据库记录了(如果没有指定 limit,则默认最多取 20 条记录)。

云函数调用数据库

使用云函数也可以调用数据库,使用开发者工具右键点击云函数根目录也就是 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()
}

然后右键点击 index.js,选择云函数增量上传:更新文件,我们既可以使用云函数的本地调试(要本地调试需要使用 npm install 安装 wx-server-sdk 依赖),也可以使用云端测试来了解云函数调用数据库的情况。

openid 与数据库

在云开发控制台的数据库标签里,打开上一节内容里的 counters 集合,在这个集合里我们可以看到每条记录除了有_id 字段以外,还有一个_openid 字段用来标志每条记录的创建者(也就是小程序的用户)。但是在我们使用管理端(控制台和云函数)中创建的数据比如我们之前导入的 zhihu_daily,就不会有 _openid 字段,因为这些记录属于管理员(不是用户)创建的记录。

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


  1. 官方文档这块缺失或者错误,我修改补充了一下。 ↩︎ ↩︎ ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值