1

使用场景:
所有的业务逻辑都仅仅需要在小程序端完成,无需过于复杂的管理逻辑

开发者可以使用云开发开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力。

云开发为开发者提供完整的原生云端支持和微信服务支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代,同时这一能力,同开发者已经使用的云服务相互兼容,并不互斥。

云开发提供了几大基础能力支持:

能力作用说明
云函数无需自建服务器在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码
数据库无需自建数据库一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库
存储无需自建存储和 CDN在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
云调用原生微信服务集成基于云函数免鉴权使用小程序开放接口的能力,包括服务端调用、获取开放数据等能力

云开发官方文档

云开发控制台

云开发提供了一个控制台用于可视化管理云资源。控制台包含以下几大模块。

  • 概览:查看云资源的总体使用情况
  • 用户管理:查看小程序的用户访问记录
  • 数据库:管理数据库集合、记录、权限设置、索引设置,可以添加,导入和导出数据
  • 存储管理:管理云文件、权限设置,上传的图片,视频等文件可以在存储里看到
  • 云函数:管理云函数、查看调用日志、监控记录,
  • 统计分析:查看云资源详细使用统计

1598515425590.jpg

初始化(小程序端和云函数端)

小程序端

在小程序端开始使用云能力前,需先调用 wx.cloud.init 方法完成云能力初始化

App({
  onLaunch: function () {
    if (!wx.cloud) {
      console.error('请使用 2.2.3 或以上的基础库以使用云能力')
    } else {
      wx.cloud.init({
        // env 参数说明:
        // env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
        // 此处请填入环境 ID, 环境 ID 可打开云控制台查看
        // 如不填则使用默认环境(第一个创建的环境)
        env: 'my-env-id',
        // 是否在将用户访问记录到用户管理中,在控制台中可见
        traceUser: true,
      })
    }
    this.globalData = {}
  }
})
env还可以传入对象,指定各个服务的默认环境,可选字段可以去文档里面查找
云函数端
const cloud = require('wx-server-sdk')
// 初始化 cloud
cloud.init({
  // API 调用都保持和云函数当前所在环境一致
  env: cloud.DYNAMIC_CURRENT_ENV
})

注意env 设置只会决定本次云函数 API 调用的云环境,并不会决定接下来其他被调云函数中的 API 调用的环境,在其他被调云函数中需要通过 init 方法重新设置环境。(每一个云函数都要调用 init

建议:在设置 env 时指定 cloud.DYNAMIC_CURRENT_ENV常量 (需 SDK v1.1.0 或以上) ,这样云函数内发起数据库请求、存储请求或调用其他云函数的时候,默认请求的云环境就是云函数当前所在的环境:

云函数上手

创建cloudfunctions文件夹,里面存放所有云函数,然后在项目根目录里创建 project.config.json 文件,新增 cloudfunctionRoot 字段,指定本地已存在的目录作为云函数的本地根目录,完成指定后,图标会变成“云目录图标”

{
   "cloudfunctionRoot": "./`cloudfunctions`/"
}

接着,在cloudfunctions目录上右键,选择创建一个新的Node.js云函数,命名为login,创建成功后会看到login文件夹里面有以下三个文件

  • config.json:配置文件
  • index.js:入口文件
  • package.json

WeChatcfaa4680bb2d73f39bf620876ec91148.png

登录函数

小程序有很多需求都需要拿到openid和APPID,我们都是通过与后台对接才能拿到,而在云开发中不需要这么复杂

云开发的云函数的独特优势在于与微信登录鉴权的无缝整合。当小程序端调用云函数时,云函数的传入参数中会被注入小程序端用户的 openid,开发者无需校验 openid 的正确性,因为微信已经完成了这部分鉴权,开发者可以直接使用该 openid。与 openid 一起同时注入云函数的还有小程序的 appid。

从小程序端调用云函数时,开发者可以在云函数内使用 wx-server-sdk 提供的 getWXContext 方法获取到每次调用的上下文(appidopenid 等),无需维护复杂的鉴权机制,即可获取天然可信任的用户登录态(openid)。

下面就是具体的实现方法:

const cloud = require('wx-server-sdk')
// 初始化 cloud
cloud.init({
  // API 调用都保持和云函数当前所在环境一致
  env: cloud.DYNAMIC_CURRENT_ENV
})
/**
 * 这个示例将经自动鉴权过的小程序用户 openid 返回给小程序端
 * event 参数包含小程序端调用传入的 data
 */
exports.main = async (event, context) => {
  console.log(event)
  console.log(context)
  // 可执行其他自定义逻辑
  // console.log 的内容可以在云开发云函数调用日志查看
  // 获取 WX Context (微信调用上下文),包括 OPENID、APPID、及 UNIONID(需满足 UNIONID 获取条件)等信息
  const wxContext = cloud.getWXContext()
  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
    env: wxContext.ENV,
  }
}
云函数的传入参数有两个,一个是 event 对象,一个是 context 对象。
event 指的是触发云函数的事件,当小程序端调用云函数时,event 就是小程序端调用云函数时传入的参数,外加后端自动注入的小程序用户的 openid 和小程序的 appid。
context 对象包含了此处调用的调用信息和运行状态,可以用它来了解服务运行的情况。
在模板中也默认 requirewx-server-sdk,这是一个帮助我们在云函数中操作数据库、存储以及调用其他云函数的微信提供的库

UnionID云函数获取途径

如果满足下面两种条件,也可以直接在云函数里拿到用户的unionid

  1. 小程序端调用云函数时,如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号,可在云函数中通过 cloud.getWXContext 获取 UnionID。
  2. 小程序端调用云函数时,如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用,也可在云函数中通过 cloud.getWXContext 获取 UnionID。

在小程序端调用这个云函数前,我们需要先将这个云函数部署到云端才可以。在云函数目录上右键,可以将云函数整体打包上传并部署到线上环境中。

截屏2020-08-27下午5.36.26.png

上传成功后login文件夹的icon会变成绿色的,证明我们已经部署成功了

image

我们可以到云开发控制台>云函数的云函数列表里面看到我们部署的云函数

WeChatb2a9dea3b1f0a736f29b8cd3c019d69a.png

部署完成后,我们可以在小程序中调用该云函数:

小程序端调用云函数

wx.cloud.callFunction({
      name: 'login', // 云函数的文件夹名
      data: {},
      success: res => {
        console.log('[云函数] [login] user openid: ', res.result.openid)
        app.globalData.openid = res.result.openid
      },
      fail: err => {
        console.error('[云函数] [login] 调用失败', err)
      }
})

可以到Netword > cloud里面看到请求
WeChat4904655db540f03a4cb4d2f390749f0e.png

数据库

打开云开发控制台的数据库标签,通过 "添加集合" 入口创建一个集合。假设我们要创建一个待办事项小程序,我们创建一个名为 counters 的集合。创建成功后,可以看到 counters 集合管理界面,界面中我们可以添加记录、查找记录、管理索引、管理权限和导入导出数据
WeChat374961ec03df70e758137a2315cf6307.png

增删改查(SDK)

了解了数据库之后我们开始学习如何在小程序端使用API进行增删改查操作,在那之前我们需要先需要先获取数据库的引用

const db = wx.cloud.database()

如需获取其他环境的数据库引用,可以在调用时传入一个对象参数,在其中通过 env 字段指定要使用的环境。此时方法会返回一个对测试环境数据库的引用。

示例:假设有一个环境名为 test,用做测试环境,那么可以如下获取测试环境数据库:

const testDB = wx.cloud.database({
  env: 'test'
})

如果要操作counters集合需先获取它的引用。在获取了数据库的引用后,就可以通过数据库引用上的 collection 方法获取一个集合的引用了

const counters = db.collection('counters')

可以通过在集合对象上调用 add 方法往集合中插入一条记录

onAdd: function () {
    const db = wx.cloud.database()
    db.collection('counters').add({
      data: {
        count: 1
      },
      success: res => {
        // 在返回结果中会包含新创建的记录的 _id
        this.setData({
          counterId: res._id,
          count: 1
        })
        wx.showToast({
          title: '新增记录成功',
        })
        console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id)
      },
      fail: err => {
        wx.showToast({
          icon: 'none',
          title: '新增记录失败'
        })
        console.error('[数据库] [新增记录] 失败:', err)
      }
    })
  }

在创建成功之后,我们可以在控制台中查看到刚新增的数据。

Promise 风格也是支持的,只要传入对象中没有 success, failcomplete,那么 add 方法就会返回一个 Promise:

onAdd: function () {
    const db = wx.cloud.database()
    db.collection('counters').add({
      data: {
        count: 1
      }
    })
    .then(res => {
      wx.showToast({
        title: '新增记录成功',
      })
    })
}

在记录和集合上都有提供 get 方法用于获取单个记录或集合中多个记录的数据。

获取一个记录的数据

假设我们已有一个 ID 为 counters-identifiant 的在集合 counters 上的记录,那么我们可以通过调用 doc 方法获取这条记录:

db.collection('counters').doc('counters-identifiant').get({
      success: function(res) {
        // res.data 包含该记录的数据
        console.log(res)
      }
})
获取多个记录的数据

我们也可以一次性获取多条记录。通过调用集合上的 where 方法可以指定查询条件,再调用 get 方法即可只返回满足指定查询条件的记录

db.collection('counters').where({
  _openid: 'user-open-id',
  done: false
})
.get({
  success: function(res) {
    // res.data 是包含以上定义的两条记录的数组
    console.log(res.data)
  }
})
获取一个集合的数据

在小程序中我们需要尽量避免一次性获取过量的数据,只应获取必要的数据。为了防止误操作以及保护小程序体验,小程序端在获取集合数据时服务器一次默认并且最多返回 20 条记录,云函数端这个数字则是 100。开发者可以通过 limit 方法指定需要获取的记录数量,但小程序端不能超过 20 条,云函数端不能超过 100 条

db.collection('todos').get({
  success: function(res) {
    // res.data 是一个包含集合中有权限访问的所有记录的数据,不超过 20 条
    console.log(res.data)
  }
})

更新数据主要有两个方法:

API说明
update局部更新一个或多个记录
set替换更新一个记录
局部更新
onCounterInc: function() {
    const db = wx.cloud.database()
    const newCount = this.data.count + 1
    db.collection('counters').doc(this.data.counterId).update({
      data: {
        count: newCount
      },
      success: res => {
        this.setData({
          count: newCount
        })
      },
      fail: err => {
        icon: 'none',
        console.error('[数据库] [更新记录] 失败:', err)
      }
    })
  }
替换更新

如果需要替换更新一条记录,可以在记录上使用 set 方法,替换更新意味着用传入的对象替换指定的记录:

onCounterInc: function() {
    const db = wx.cloud.database()
    const newCount = this.data.count + 1
    db.collection('counters').doc(this.data.counterId).set({
      data: {
        description: "learn cloud database",
        count: newCount,
        style: {
          color: "skyblue"
        },
        item: 'apple',
        done: true
      },
      success: res => {
      },
      fail: err => {
        icon: 'none',
        console.error('[数据库] [更新记录] 失败:', err)
      }
    })
}
删除一条记录

对记录使用 remove 方法可以删除该条记录,比如:

onRemove: function() {
    if (this.data.counterId) {
      const db = wx.cloud.database()
      db.collection('counters').doc(this.data.counterId).remove({
        success: res => {
          wx.showToast({
            title: '删除成功',
          })
          this.setData({
            counterId: '',
            count: null,
          })
        },
        fail: err => {
          wx.showToast({
            icon: 'none',
            title: '删除失败',
          })
          console.error('[数据库] [删除记录] 失败:', err)
        }
      })
    } else {
      wx.showToast({
        title: '无记录可删,请先创建一个记录',
      })
    }
},
删除多条记录

如果需要更新多个数据,需在 Server 端进行操作(云函数)。可通过 where 语句选取多条记录执行删除,只有有权限删除的记录会被删除。比如删除所有done = true的

// 使用了 async await 语法
const cloud = require('wx-server-sdk')
const db = cloud.database()

exports.main = async (event, context) => {
  try {
    return await db.collection('counters').where({
      done: true
    }).remove()
  } catch(e) {
    console.error(e)
  }
}

更多数据库的操作可以去官方文档里面学习

存储

云存储提供高可用、高稳定、强安全的云端存储服务,支持任意数量和形式的非结构化数据存储,如视频和图片,并在控制台进行可视化管理。云存储包含以下功能:

  • 存储管理:支持文件夹,方便文件归类。支持文件的上传、删除、移动、下载、搜索等,并可以查看文件的详情信息
  • 权限设置:可以灵活设置哪些用户是否可以读写该文件夹中的文件,以保证业务的数据安全
  • 上传管理:在这里可以查看文件上传历史、进度及状态
  • 文件搜索:支持文件前缀名称及子目录文件的搜索
  • 组件支持:支持在 imageaudio 等组件中传入云文件 ID
上传文件

在小程序端可调用 wx.cloud.uploadFile 方法进行上传:

wx.cloud.uploadFile({
  cloudPath: 'example.png', // 上传至云端的路径
  filePath: '', // 小程序临时文件路径
  success: res => {
    // 返回文件 ID
    console.log(res.fileID)
  },
  fail: console.error
})

上传成功后会获得文件唯一标识符,即文件 ID,后续操作都基于文件 ID 而不是 URL。

下载文件

可以根据文件 ID 下载文件,用户仅可下载其有访问权限的文件:

wx.cloud.downloadFile({
  fileID: '', // 文件 ID
  success: res => {
    // 返回临时文件路径
    console.log(res.tempFilePath)
  },
  fail: console.error
})
删除文件

可以通过 wx.cloud.deleteFile 删除文件:

wx.cloud.deleteFile({
  fileList: ['a7xzcb'],
  success: res => {
    // handle success
    console.log(res.fileList)
  },
  fail: console.error
})

更详细的 API 可参考小程序端及后端存储 API 文件。

组件支持

支持在 imageaudio 等组件中传入云文件 ID

换取临时链接

可以根据文件 ID 换取临时文件网络链接,文件链接有有效期为两个小时:

wx.cloud.getTempFileURL({
  fileList: ['cloud://xxx.png'],
  success: res => {
    // fileList 是一个有如下结构的对象数组
    // [{
    //    fileID: 'cloud://xxx.png', // 文件 ID
    //    tempFileURL: '', // 临时文件网络链接
    //    maxAge: 120 * 60 * 1000, // 有效期
    // }]
    console.log(res.fileList)
  },
  fail: console.error
})

familyAboveAll
156 声望17 粉丝