草庐IT

微信小程序 之 云开发

玄鱼殇 2024-05-27 原文

一、概念

1. 传统开发模式

2. 新开发模式 ( 云开发模式 )

3. 传统、云开发的模式对比

4. 传统、云开发的项目流程对比

5. 云开发的定位

1. 个人的项目或者想法,不想开发服务器,直接使用云开发
2. 某些公司的小程序项目是使用云开发的,但是不多,大部分还是用自己的服务器
3. 可以让我们了解一些云开发的思想,比如服务器、数据库、存储,有利于之后学习服务器相关知识

6. 云开发核心技术

云开发主要包含三大核心技术 : 云数据库、云存储、云函数

云数据库

  • 提供在小程序端直接对数据库进行增删改查的能力

  • 数据库是类似于MongoDB的文档存储的数据库,操作非常方便

  • 非常简单,不是关系数据库,可以直接往里面存储JSON对象

云存储

  • 可以在小程序端直接上传、下载、删除文件

  • 自带CDN,提高文件访问速度

  • 可以获取临时链接,支持在小程序外访问

云函数

  • 提供了在服务器代码的执行能力

  • 包含微信天然的私有鉴权

  • 更大权限的操作数据库等

  • 进行云调用、HTTP请求等操作

二、创建云开发项目

1. 创建项目

2. 了解云开发

01 - 打开云开发

02 - 创建云开发环境

  • 新建新环境

  • 设置 – 环境名称 – 创建环境

03 - 云开发控制台

  • 运营分析

  • 数据库(云数据库)

  • 存储(云存储)

  • 云函数

04 - 环境与配额

环境
  • 一个环境对应一整套独立的云开发资源,包括数据库、存储空间、云函数等资源

  • 各个环境是相互独立的,用户开通云开发后即创建了一个环境,默认可拥有最多两个环境

  • 在实际开发中,建议多配备几个环境

  • 测试环境

  • 预发环境

  • 线上环境

配额
  • 可以根据自己的业务量选择对应的更高配额

3. 云开发项目初始化

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

01 - 在app.js 中初始化

// app.js
App({
  onLaunch: function () {
    // 1. 判断是否有云开发能力
    if (!wx.cloud) {
      console.error('请使用 2.2.3 或以上的基础库以使用云能力');
    } else {
      // 2. 初始化云开发
      wx.cloud.init({
        /**
         * env
         * env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
         * 此处请填入环境 ID, 环境 ID 可打开云控制台查看
         */
        env: 'my-env-id',
        /**
         * traceUser
         * 是否要跟踪用户
         * 打开后,可在 云开发控制台 - 运营分析 - 用户访问,观看到访问列表
         */
        traceUser: true,
      });
    }
    this.globalData = {};
  }
});

02 - 路径可进行配置

三、云数据库

1. 概念

网址 : 微信开发文档 - 云数据库

数据库介绍

  • JSON数据库

  • 云开发提供了一个文档型数据库,类似于MongoDB,里面存放的是一条条JSON格式的对象

  • 一个数据库可以包含多个集合,一个集合中包含多个JSON对象

  • 提供方便的API调用:学习这些API即可

  • 提供了小程序端和服务器端(云函数)中调用的区分

数据库集合的权限

若想每个人都 可读 可写

2. 操作数据库 – 控制台操作

01 - 打开

02 - 创建集合

相当于是一个数组 []

03 - 创建一条数据 ( 记录 )

相当于是数组 [] 中的一条数据

默认模式

JSON模式

04 - 导入数据

3. 操作数据库 - 代码操作

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const stuCollect = db.collection('students')

增加数据

在数据库中刷新即可看到新增加的数据
ps : 代码添加的数据,_openid字段也会新增上,作为唯一标识
  • 获取操作后的回调结果

  • 基于回调:传入success、fail、complete

  • 基于Promise:使用then、catch、finally

添加单条数据

// 1. 获取对应的数据库
const db = wx.cloud.database()
// 2. 获取到要操作的集合 (collection)
const stuCollect = db.collection('students')

Page({
  // 新增数据
  addData() {
    stuCollect.add({
      // 数据
      data: {
        name: '小王',
        age: 20,
        hobbies: ['bvvv'],
        address: {
          alias: 'HB',
          name: '湖北',
          code: '333343'
        }
      },
      // 可以使用回调函数
      success: ({ errMsg }) => {
        if (errMsg === 'collection.add:ok') {
          wx.showToast({
            title: '添加成功',
          })
        }
      }
    })
    // // 也可以使用promise
    // .then((res) => { console.log(res) })
  }
})

循环添加数据

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const yzCollect = db.collection('YZ')

Page({
  // 增加数据
  onAdd() {
    // 请求10页的数据
    for (let i = 1; i <= 10; i++) {
      wx.request({
        // 测试用途 : 抓取下某鱼的数据
        url: 'https://m.douyu.com/api/room/list',
        data: {
          page: i,
          type: 'yz'
        },
        success: (res) => {
          const list = res.data.data.list
          this.addData(list)
        }
      })
    }
  },
  addData(list) {
    list.forEach(item => {
      // 循环添加数据
      yzCollect.add({
        data: item
      }).then(() => {
        console.log(`${item.roomName}:添加成功`);
      })
    })
  },
})

删除数据

根据 id 删除

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const stuCollect = db.collection('students')

Page({
  onDelete() {
    // 3. 根据id删除某一条数据  =>  id去数据库里看即可
    stuCollect.doc('a64480e663f0753e000826875146d365')
      .remove()
      .then(res => {
        console.log(res);
      })
  }
})

根据 条件 删除

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const stuCollect = db.collection('students')

Page({
  // 3. 根据条件删除数据
  onDelete() {
    // 删除 名称 => coder 的数据
    stuCollect.where({
      name: 'coder'
    })
      .remove()
      .then(res => {
        console.log(res);
      })

    // 删除 年龄 => 大于16岁 的数据
    // 01.拿到查询指令
    const cmd = db.command
    stuCollect.where({
      // 02.使用查询指令  gt => >   lt => <
      age: cmd.gt(16)
    })
      .remove()
      .then(res => {
        console.log(res);
      })
  }
})

修改数据

修改单条数据

更新数据
update : 更新(增加)某一个字段
// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const stuCollect = db.collection('students')

Page({
  // 修改
  onEdit() {
    stuCollect.doc('632b810463f08152000634f45aa33965')
      // update : 修改某一个字段
      .update({
        data: {
          age: 99
        }
      }).then(res => {
        console.log(res);
      })
  }
})
替换数据
set : 使用新对象替换原来对象
// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const stuCollect = db.collection('students')

Page({
  // 修改
  onEdit() {
    stuCollect.doc('2cc84e2663ef492f00c7ecda28da87f4')
      // set : 原数据被全部替换
      .set({
        data: {
          age: 99
        }
      }).then(res => {
        console.log(res);
      })
  }
})

修改多条数据

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const stuCollect = db.collection('students')

Page({
  // 修改
  onEdit() {
    // 拿到查询指令
    const cmd = db.command
    stuCollect.where({
      // 条件 : 年龄小于30岁的人
      age: cmd.lt(30)
    }).update({
      data: {
        age: 20
      }
    }).then(res => {
      console.log(res);
    })
  }
})

查找数据

查询数据的方式 :

  • 方式一:通过ID查询精确的某一条数据

  • 使用doc查询ID

  • 方式二:根据条件查询满足条件的数据

  • 使用where作为条件

  • 方式三:通过指令过滤数据

  • 使用db.command的指令

  • eq => 等于

  • neq => 不等于

  • lt => 小于

  • lte => 小于或等于

  • gt => 大于

  • gte => 大于或等于

  • in => 字段值在给定数组中 ( name : cmd.in['coder','star'] )

  • nin => 字段值不在给定数组中

  • 方式四:通过正则表达式匹配符合的数据

  • 使用db.RegExp创建正则规则

  • 方式五:获取整个集合的数据(小程序端一次性最多20条,云函数中可以获取100条)

  • 直接调用get

  • 方式六:过滤、分页、排序查询数据

  • 使用field、skip、limit、orderBy

方式一 : 精准查询

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const yzCollect = db.collection('YZ')

Page({
  onQuery() {
    // 方式一 : 根据id查询某条数据
    yzCollect.doc('663f243e63f07f9700071256127340a0')
      .get()
      .then(({ data }) => {
        console.log(data);
      })
  }
})

方式二 : 条件查询

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const yzCollect = db.collection('YZ')

Page({
  onQuery() {
    // 方式二 : 根据条件查询 => 查询到的是多条数据
    yzCollect.where({
      // 不是模糊查询,但是可能是同名的
      nickname: "小野静奈",
    })
      .get()
      .then(({ data }) => {
        console.log(data); // [ {...} ]
      })
  }
})

方式三 : 指令查询

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const yzCollect = db.collection('YZ')

Page({
  onQuery() {
    // 方式三 : 查询指令 => gt => 大于  lt => 小于

    // 01 - 获取查询指令
    const _ = db.command
    yzCollect.where({
      // 02 - 使用查询指令
      rid: _.lt(9000000),
    })
      .get()
      .then(({ data }) => {
        console.log(data); // [ {...},{...} ] 小程序端一次性最多返回20条,可做分页查询
      })
  }
})

方式四 : 正则查询

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const yzCollect = db.collection('YZ')

Page({
  onQuery() {
    // 方式四 : 正则表达式查询  =>  查询包含 字母z 的数据  =>  模糊查询
    yzCollect.where({
      // nickname: db.RegExp({
      //   regexp:'z', // 包含z
      //   options:'i' // 忽略大小写
      // }),
      nickname: /z/ig
    })
      .get()
      .then(({ data }) => {
        console.log(data); // [ {...},{...} ] 小程序端一次性最多返回20条,可做分页查询
      })
  }
})

方式五 : 集合查询

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const yzCollect = db.collection('YZ')

Page({
  onQuery() {
    // 方式五 : 获取整个集合中的数据 => 直接get
    yzCollect
      .get()
      .then(({ data }) => {
        console.log(data); // [ {...},{...} ] 小程序端一次性最多返回20条,可做分页查询
      })
  }
})

方式六 : 综合查询

// 1. 获取数据库对象
const db = wx.cloud.database()
// 2. 获取操作的集合
const yzCollect = db.collection('YZ')

Page({
  // 方式六 : 综合查询
  /**
   * skip    =>   offset偏移量           =>  跳过几条数据
   * limit   =>   size                  =>  拿几条数据
   * orderBy =>   排序('des','方式')    =>  升序:asc  |  降序 : desc
   * field   =>   过滤字段               =>  拿想要的数据字段
   */
  // 
  onQuery() {
     
      // 过滤字段 => 拿 _id,nickname,rid 三个字段
      .field({
        _id: true,
        nickname: true,
        rid: true
      })
      // 跳过0条数据
      .skip(0)
      // 拿5条数据
      .limit(5)
      // 排序 => 根据rid排序,升序
      .orderBy('rid', 'asc')
      .get()
      .then(({ data }) => {
        console.log(data); // [ {_id:'', nickname:'', rid:''},{...} ] 
      })
  }
})

4. 案例

效果

wxml

<view class="nav">
  <block wx:for="{{dataList}}"
         wx:key="index">
    <view class="item">
      <view class="notice">
        <view size="mini"
              class="btn"
              bindtap="tabEdit"
              data-item="{{item}}"
              data-index="{{index}}">Edit</view>
        <text>{{item.nickname}}</text>
        <view size="mini"
              class="btn"
              bindtap="tabDel"
              data-item="{{item}}"
              data-index="{{index}}">Del</view>
      </view>
      <image src="{{item.roomSrc}}"
             mode="widthFix" />
    </view>
  </block>
</view>

wxss

.nav {
  padding: 20rpx;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 48%;
  margin-bottom: 30rpx;
  border-radius: 40rpx;
}

.notice {
  font-size: 30rpx;
  line-height: 40rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: pink;
}

.btn {
  font-size: 24rpx;
  color: gray;
}

image {
  width: 100%;
}

js

// 获取数据库对象
const db = wx.cloud.database()
// 获取集合
const yzCollect = db.collection('YZ')
Page({
  data: {
    dataList: [],
    page: 0,
    pageSize: 10
  },
  onLoad() {
    this.getDataList()
  },
  // 上拉加载更多
  onReachBottom() {
    this.getDataList()
  },

  /**
   * 方法
   */

  // 获取数据
  getDataList() {
    const { page, pageSize, dataList } = this.data
    yzCollect.field({
      nickname: true,
      roomName: true,
      roomSrc: true,
    })
      .skip(page * pageSize)
      .limit(pageSize)
      .get()
      .then(({ data }) => {
        console.log(data);
        // 保存数据
        this.setData({
          dataList: [...dataList, ...data]
        })
        this.data.page = page + 1
      })
  },
  // 编辑
  async tabEdit(e) {
    const { item, index } = e.currentTarget.dataset
    const newName = item.nickname + 'Q'
    // 更改数据库数据
    const { errMsg } = await yzCollect.doc(item._id).update({
      data: {
        nickname: newName
      }
    })
    if (errMsg !== 'document.update:ok') {
      return wx.showToast({
        title: '修改失败',
        icon: 'none'
      })
    }
    // 更改页面中数据
    this.setData({
      ['dataList[' + index + '].nickname']: newName
    })
    wx.showToast({
      title: '修改成功',
      icon: 'none'
    })
  },
  // 删除
  async tabDel(e) {
    const { item, index } = e.currentTarget.dataset
    // 删除数据库数据
    const { errMsg } = await yzCollect.doc(item._id).remove()
    if (errMsg !== 'document.remove:ok') {
      return wx.showToast({
        title: '删除失败',
        icon: 'none'
      })
    }
    // 删除页面中数据
    this.data.dataList.splice(index, 1)
    this.setData({
      dataList: this.data.dataList
    })
    wx.showToast({
      title: '删除成功',
      icon: 'none'
    })
    // 判断当前页面数量是否小于pageSize,在第一页时可能会出现镂空现象
    if (this.data.dataList.length < this.data.pageSize) {
      this.getDataList()
    }
  },
})

四、云存储

1. 概念

网址 : 微信开发文档 - 云存储

云存储用于将文件存储到云端 :

  • 云存储提供高可用、高稳定、强安全的云端存储服务

  • 持任意数量和形式的非结构化数据存储,如视频和图片

  • 并在控制台进行可视化管理

云存储常见的操作 :

  • 上传文件到云存储中(图片、视频、音频等等都可以)

  • 获取文件的临时链接(在外网可以访问)

  • 下载文件到本地(本地文件缓存)

  • 将云存储中的文件删除

2. 操作云存储 - 控制台操作

01 - 上传

图片、视频、音频等

02 - 页面展示

3. 操作云存储 - 代码操作

上传操作

Page({
  data: {
    imagePath: ""
  },
  
  // 上传文件
  async onUploadTap() {
    // 1. 选中本地文件( 相册、拍照 )
    const { type, errMsg, tempFiles } = await wx.chooseMedia({
      // 设定一次只能传一张图片
      count: 0
    })
    if (errMsg !== 'chooseMedia:ok') {
      return wx.showToast({
        title: '上传失败',
      })
    }
    console.log(type, errMsg, tempFiles);
    // 2. 获取照片
    const imagePath = tempFiles[0].tempFilePath
    // 3. 因为图片名称容易重复,所以这里设定一下
    const imageName = this.setImageName(imagePath)
    // 4. 将照片上传到云存储中
    const uploadRes = await wx.cloud.uploadFile({
      // 文件路径 => 文件名称,如果在images文件家中,前面带上即可 => images/abc.png
      cloudPath: 'images/' + imageName,
      // 指定要上传的文件的小程序临时文件路径
      filePath: imagePath,
    })
    console.log(uploadRes);
    if (uploadRes.errMsg !== 'cloud.uploadFile:ok') {
      return wx.showToast({
        title: '上传失败',
      })
    }
    wx.showToast({
      title: '上传成功',
    })
    // 5. 页面展示
    this.setData({
      imagePath: uploadRes.fileID
    })
  },

  // 图片名称设定
  setImageName(imagePath) {
    // 1. 时间戳
    const timeStamp = new Date().getTime()
    // 2. openid
    const openid = 'openid'
    // 3. 文件后缀名  pop => 拿到最后一个元素   
    const extension = imagePath.split(".").pop()
    // 返回拼接名称
    return `${timeStamp}_${openid}.${extension}`
  }
})

下载操作

Page({
  data: {
    imagePath: ""
  },

  // 一、点击下载
  onDownload() {
    // 1. 获取手机相册权限
    wx.authorize({
      scope: 'scope.writePhotosAlbum',
      success: () => {
        // 2. 从云存储中获取下载的文件路径
        this.getDownPath()
      },
      fail: () => {
        wx.showToast({
          title: '未授权,请前往微信设置页面中打开授权',
          icon: 'none'
        })
      }
    })
  },

  // 二、获取下载的文件地址
  async getDownPath() {
    //  根据fileID获取下载的文件路径
    const { errMsg, tempFilePath } = await wx.cloud.downloadFile({
      // fileID
      fileID: "cloud://xuanyu-dev"
    })
    if (errMsg !== 'downloadFile:ok') {
      return wx.showToast({
        title: '下载失败',
        icon: 'none'
      })
    }
    // 3. 保存文件到手机相册
    this.saveFile(tempFilePath)
    // 也可展示到页面上
    this.setData({
      imagePath: tempFilePath
    })
  },

  // 三、保存文件到手机相册
  saveFile(filePath) {
    // 下载图片到手机本地
    wx.saveImageToPhotosAlbum({
      filePath,
      success: ({ errMsg }) => {
        if (errMsg !== 'saveImageToPhotosAlbum:ok') {
          return wx.showToast({
            title: '下载失败',
            icon: 'none'
          })
        }
        wx.showToast({
          title: '下载成功',
          icon: 'none'
        })
      }
    })
  }
})

删除操作

Page({
  // 点击删除
  async onDelete() {
    const { errMsg } = await wx.cloud.deleteFile({
      fileList: [
        // fileID
        'cloud://xuanyu-dev'
      ],
    })
    if (errMsg !== 'cloud.deleteFile:ok') {
      return wx.showToast({
        title: '删除失败',
        icon: 'none'
      })
    }
    wx.showToast({
      title: '删除成功',
      icon: 'none'
    })
  },
})

临时链接

为什么要获取临时链接 :

  • 我们将文件上传到云存储后,可以通过fileID在小程序中直接访问

  • 但是,如果我们希望在小程序以外的地方访问(比如浏览器、手机端),那么fileID是不可以的

  • 这个时候,我们可以通过获取临时链接,该链接可以在小程序以外访问

  • 注意:文件链接有效期为两个小时

Page({
  // 生成临时文件链接
  async onTemplate() {
    // 1. 请求临时链接
    const { errMsg, fileList } = await wx.cloud.getTempFileURL({
      fileList: [
        // fileID
        'cloud://xuanyu-dev',
        'cloud://xuanyu-dev'
      ],
    })
    if (errMsg !== 'cloud.getTempFileURL:ok') {
      return wx.showToast({
        title: '生成链接失败',
        icon: 'none'
      })
    }
    // 2. 获取结果
    const resUrl = fileList.map(item => {
      return item.tempFileURL
    })
    console.log(resUrl);
    wx.showToast({
      title: '生成链接成功',
      icon: 'none'
    })
  },
})

五、云函数和云调用

1. 概念

云函数即在云端(服务器端)运行的函数 :

  • 在物理设计上,一个云函数可由多个文件组成,占用一定量的CPU 内存等计算资源

  • 云函数完全独立,可分别部署在不同的地区

  • 开发者无需购买、搭建服务器,只需编写函数代码并部署到云端即可在小程序端调用

  • 同时云函数之间也可互相调用

云函数的编写方式 :

  • 一个云函数的写法与一个在本地定义的 JavaScript 方法无异,代码运行在云端 Node.js 中

  • 当云函数被小程序端调用时,定义的代码会被放在Node.js 运行环境中执行

  • 可以如在 Node.js 环境中使用 JavaScript 一样在云函数中进行网络请求等操作,而且还可以通过云函数后端 SDK搭配使用多种服务,比如使用云函数 SDK 中提供的数据库和存储 API 进行数据库和存储的操作

云开发的云函数的独特优势在于与微信登录鉴权的无缝整合 :

  • 当小程序端调用云函数时,云函数的传入参数中会被注入小程序端用户的 openid,开发者无需校验 openid 的正确性因为微信已经完成了这部分鉴权,开发者可以直接使用该 openid

云函数作用 :

  • 在云函数中对云数据库进行操作

  • 对结果进行某种转换,再返回到小程序端

  • 在云函数中对云存储进行操作

  • 进行查询、上传、删除等操作

  • 向其他服务器发送请求

  • 请求到数据后,再返回到小程序端(云函数中对域名、ip没有限制)

  • . . . . . .

2. 使用过程

01 - 选择环境

02 - 同步云函数

03 - 下载代码到本地

04 - 创建云函数

05 - 编写代码逻辑

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境


// 云函数入口函数
exports.main = async (event, context) => {
  return 'hello world'
}

06 - 将云函数上传到云端

07 - 小程序中对云函数调用

Page({
  async onLoad() {
    // 1. 调用云函数
    const { errMsg, requestID, result } = await wx.cloud.callFunction({
      // 2. 指定调用哪个云函数
      name: 'testFunc'
    })
    console.log(result); // 'hello world'
  }
})

3. 基本使用

案例 : 云函数来计算两个数字的和

01 - 本地代码

Page({
  async onLoad() {
    // 1. 调用云函数
    const { errMsg, requestID, result } = await wx.cloud.callFunction({
      // 2. 指定调用哪个云函数
      name: 'testFunc',
      // 3. 传入数据到云函数
      data: {
        num1: 10,
        num2: 20
      }
    })
    console.log(result); // 30
  }
})

02 - 云函数代码

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境


// 云函数入口函数
exports.main = async (event, context) => {
  // 1. 获取调用者传入的参数,就是在data中传过来的参数
  // console.log(event); // 因为显示在云端,所以这样是看不到结果的
  const { num1, num2 } = event
  
  // 2. 返回结果
  return num1 + num2
}

03 - 部署云函数

右键,上传并部署即可

4. 云函数代码调试

云端测试

缺点 : 看不到打印信息

01 - 找到云函数

02 - 云端测试

本地调试

01 - 找到云函数

02 - 本地调试

安装依赖
开启成功
重新请求
更改代码

5. 高级使用

云函数 - 获取openID

微信内部做好了身份鉴权,在云函数中可直接拿到登录者的openID
openid可以用于作为用户身份的标识符,在云开发中可以获取用户openid来验证用户是否已经登录

在云函数中获取微信调用上下文 :

  • Cloud.getWXContext(): Object

云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境

// 云函数入口函数
/**
 * event   :  传递过来的参数
 * context :  node运行环境上下文,一般不会用到
 */
exports.main = async (event, context) => {
  // 1. 获取到微信的上下文
  const wxContext = cloud.getWXContext()

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}

本地调用

Page({
  async onLoad() {
    // 1. 调用云函数
    const { errMsg, requestID, result } = await wx.cloud.callFunction({
      // 2. 指定调用哪个云函数
      name: 'getOpenid',
    })
    console.log(errMsg, requestID, result); 
  }
})

云函数 – 操作云数据库

小程序端口对数据库的操作有限制 :

  • 小程序端一次最多获取20条数据 => 云函数最多100条

  • 小程序端一次性删除、修改多条数据可能会报警告 => 云函数中没有限制

云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境

// 云函数入口函数
exports.main = async (event, context) => {
  // 1. 获取数据库
  const db = cloud.database()
  // 2. 获取集合
  const _ = db.collection('YZ')
  // 3. 从集合中查询数据
  return await _.get()
}

本地调用

Page({
  async onLoad() {
    // 1. 调用云函数
    const { result } = await wx.cloud.callFunction({
      // 2. 指定调用哪个云函数
      name: 'getYZdata',
    })
    console.log(result.data); // [{...}, {...}, {...}, ...]
  }
})

云函数 – 操作云存储

云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境

// 云函数入口函数
exports.main = async (event, context) => {
  // 1. 下载操作 => 下载下来文件,不是地址,不知道干嘛用的,又不能保存在本地
  const { errMsg: downErrMsg, fileContent } = await cloud.downloadFile({
    // fileID
    fileID: "cloud://xuanyu-dev"
  })
  if (downErrMsg !== 'downloadFile:ok') {
    return downErrMsg
  }
  // return fileContent.toString('utf8')

  // 2. 删除操作
  const { errMsg: delErrMsg } = await cloud.deleteFile({
    fileList: [
      'cloud://xuanyu-dev'
    ],
  })
  if (delErrMsg !== 'deleteFile:ok') {
    return delErrMsg
  }
  return 'OK'
}

本地调用

Page({
  data: {
    qrCodeUrl: ''
  },
  async onLoad() {
    // 1. 调用云函数
    const { result } = await wx.cloud.callFunction({
      // 2. 指定调用哪个云函数
      name: 'fetchData',
    })
    console.log(result);
  }
})

云函数 – 发送http请求

对于小程序某些域名的限制无法配置时,我们可以通过云函数作为代理来请求数据,再返回给小程序端
需要使用axios,所以需安装
ps :
npm i axios@0.27.2 => 如果安装高版本的,可能会出问题

返回的结果时,如果出现以下问题,可能是格式问题,返回.data或者详细的数据即可

云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')
const axios = require('axios')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境

// 云函数入口函数
exports.main = async (event, context) => {
  // 1. 从其他服务器中请求数据
  const res = await axios.get('http://www.baidu.com')
  // 2. 对数据进行转换

  // 3. 返回数据到小程序端   =>   这里要返回.data   否则可能会报错
  return res.data
}

本地调用

Page({
  async onLoad() {
    // 1. 调用云函数
    const { result } = await wx.cloud.callFunction({
      // 2. 指定调用哪个云函数
      name: 'fetchData',
    })
    console.log(result);
  }
})

云函数 – 生成小程序码

网址 : 微信官方文档 - 生成二维码

云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境

// 云函数入口函数
exports.main = async (event, context) => {
  // 1. 生成小程序码
  const { contentType, errMsg: codeErrMsg, buffer } = await cloud.openapi.wxacode.createQRCode({
    "path": 'pages/cloud-database/index',
    "width": 320
  })
  if (codeErrMsg !== 'openapi.wxacode.createQRCode:ok') {
    // 生成二维码失败
    return codeErrMsg
  }

  // 2. 获取图片数据,上传到云存储中
  const timeStamp = new Date().getTime()
  const openid = cloud.getWXContext().OPENID
  const ext = contentType.split('/').pop()
  const { errMsg: uploadErrMsg, fileID } = await cloud.uploadFile({
    // 文件内容,注 : 这里没有filePath
    fileContent: buffer,
    cloudPath: `qrcode_${timeStamp}_${openid}.${ext}`
  });
  if (uploadErrMsg !== 'uploadFile:ok') {
    // 存储二维码失败
    return uploadErrMsg
  }

  // return fileID
  // 可直接返回fileID | 或者多一步,返回临时路径
  // 3. 获取图片临时路径
  const { errMsg: getTempErrMsg, fileList } = await cloud.getTempFileURL({
    fileList: [fileID]
  })
  if (getTempErrMsg !== 'getTempFileURL:ok') {
    // 获取二维码失败
    return getTempErrMsg
  }

  // 4. 返回临时图片路径
  return fileList[0].tempFileURL
}

本地调用

Page({
  data: {
    qrCodeUrl: ''
  },
  async onLoad() {
    // 1. 调用云函数
    const { result } = await wx.cloud.callFunction({
      // 2. 指定调用哪个云函数
      name: 'fetchData',
    })
    this.setData({
      qrCodeUrl: result
    })
    console.log(result);
  }
})

有关微信小程序 之 云开发的更多相关文章

  1. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

  2. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  3. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  4. Ubuntu20.04系统WineHQ7.0安装微信 - 2

    提供3种Ubuntu系统安装微信的方法,在Ubuntu20.04上验证都ok。1.WineHQ7.0安装微信:ubuntu20.04安装最新版微信--可以支持微信最新版,但是适配的不是特别好;比如WeChartOCR.exe报错。2.原生微信安装:linux系统下的微信安装(ubuntu20.04)--微信适配的最好,反应最快,但是微信版本只到2.1.1,版本太老,很多功能都没有。3.深度deepin-wine6安装微信:ubuntu20.04+系统deepin-wine6安装新版微信--综合比较好,当前个人使用此种方法1个月,微信版本3.4;没什么大问题,尚可。一、WineHQ7.0安装微信

  5. 微信小程序订餐系统 - 2

    对传统的餐饮商家来说,小程序很好地解决了餐厅线下线上连接的问题,在引流获客、节约人力、营销宣传、塑造会员体系、改善消费体验等方面都有很大帮助。小程序点餐可以帮助餐饮企业节省一大把人力开支。一个包含扫码点单、菜品管理、优惠券推送、外卖配送的小程序,商家花几万元就能完成开发测试并投入。商家为什么要开通“扫码点餐”1.解决服务员不够用的问题。2.不怕顾客跑单漏单。3.在微信就能管理菜品、查看营业额。4.订单小票显示顾客桌号和已点菜品。5.可在“附近的小程序”找到您的门店。如今餐饮业常用的三种经营模式:1堂食点单模式客人通过小程序堂食点单。商家可以在微信扫码点餐小程序管理后台根据自己店内情况来设置不同

  6. 最新版人脸识别小程序 图片识别 生成二维码签到 地图上选点进行位置签到 计算签到距离 课程会议活动打卡日常考勤 上课签到打卡考勤口令签到 - 2

    技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进

  7. 微信小程序切换云环境 - 2

    在开发微信小程序的时候,我们可能需要开发环境和测试环境,或者其他环境,下面是切换环境的方法。首先需要明确的是:前端的页面代码是不区分环境的,环境的区分指的是云函数、云数据库、云存储这些。1、更改云函数的使用云环境这里我们从cloud1更改为test-cloud,这个改完是没有用的,因为在前端代码指定了使用的云环境。cloudfunctions文件和miniprogram文件虽然都在一个目录下,但是这两个没有直接联系。2、在evList.js中添加自己云环境evList.js存储了云环境列表,这里把test-cloud加到这个列表里,需要填写envId和alias,参照cloud1写就行。3、更

  8. Spring Boot中的微信支付(小程序) - 2

    前言微信支付是企业级项目中经常使用到的功能,作为后端开发人员,完整地掌握该技术是十分有必要的。一、申请流程和步骤图1-1注册微信支付账号获取微信小程序APPID获取微信商家的商户ID获取微信商家的API私钥配置微信支付回调地址绑定微信小程序和微信支付的关系搭建SpringBoot工程编写后台支付接口发布部署接口服务项目使用微信小程序或者UniAPP调用微信支付功能支付接口的封装配置jwt或者openid的token派发原生微信小程序完成支付对接二、注册商家2.1商户平台商家或者企业想要通过微信支付来进行商品的销售,必须先通过微信平台(pay.weixin.qq.com)去将商家进行注册。注册成

  9. 微信小程序顶部标题栏与胶囊对齐 - 2

    介绍    最近在做微信小程序时,顶部标题栏总是与胶囊对不齐。往往是在这款手机上对齐了,在另外一款手机差很多。我在查阅资料后,提出了一种方法解决这个问题,即:在页面onLoad或组件created时,利用微信小程序提供的API,获取系统状态栏高度和胶囊信息,进而动态调整顶部标题栏样式。在苹果、小米、荣耀手机做验证,能做到精准对齐。理论        胶囊样式应该是垂直居中,有1px的border,border-radius为18px。        若要使顶部标题栏与胶囊对齐,则其高度必须是导航栏高度,标题栏内容也要垂直居中,顶部标题栏的外边距或内边距必须是状态栏高度。        如果顶部

  10. 软件工程毕业设计课题(81)微信小程序毕业设计PHP校园跑腿小程序系统设计与实现 - 2

        项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于微信校园跑腿小程序系统,前台用户使用小程序发布跑腿任何和接跑腿任务,后台管理使用基于PHP+MySql的B/S架构;通过后台管理跑腿的用户、查看跑腿信息和对应订单。意义:手机网络时代,大学生通过手机网购日常用品、外卖外卖、代取快递等已不再是稀奇的事情。此外,不少高校还流行着校园有偿工作,校园跑腿就成了大学生创业服务项目。        因为你在校园里,所以不会有进入的限制。并不是所有的外卖平台都可以随意进入校园,比如小黄和小蓝的双打外卖平台。许多大学禁止送餐进入学校,更不用说送餐进入宿舍了。这一措施使得校园服务市场的竞争相对不

随机推荐