微信小程序开发(二)----- 云开发

1、概念

  • 微信小程序的云开发是腾讯云与微信团队深度合作推出的一个全新的小程序的解决方案,它提供了云函数、云数据库与云存储这三大基础能力支持,随着云开发的出现,小程序的开发者可以将服务端的部署和运营的环节进行服务端的托管,让腾讯云去管理,而不需要在运维和管理方面投入太多的精力。

            

2、传统小程序开发与云开发的区别

  • 小程序传统开发模式:(开发效率低、运维成本高)
           对于小程序传统的开发模式而言,我们需要一个客户端(也就是前端页面),而前端页面展示的数据大多来自于数据库,因此我们还需要一个服务端,把后端的代码以及数
    据库部署上去,并且前后端联调的过程也是沟通的过程,时间成本比较高;小程序在部署的时候,我们需要购买相对应的域名以及服务器,并且还要进行备案(非常麻烦、耗时长),
    部署成功后,在运维小程序的过程中,也会遇到很多很多的问题,比如DB运维、文件存储、内容加速(CDN)、网络防护、容器服务、负载均衡以及安全加固等;虽然有的公司没有
    购买服务器,使用的是阿里云或者腾讯云上面的服务,但是依旧需要维护,因此运维成本非常高。

          

  • 小程序云开发模式:采用serverless(无服务)模式
          对于小程序的云开发模式而言,依旧需要一个客户端,但是由于小程序提供了云开发,而云开发提供了云函数、云数据库以及云存储三大基础能力支持,我们可以直接在客户
    端调用云数据库里面的内容,当然也可以通过客户端调用云函数,在云函数里面处理一些业务逻辑,并在云函数里面调用云数据库,同时我们可以在客户端上传相应的文件到云存储当
    中,或者将云存储中的图片下载到客户端给用户去展示,由于云开发是部署在腾讯云上面的,因此我们不需要额外的运维人员,运维成本也会降低。除此之外,小程序中的云函数采用
    的是Node.js,云数据库采用的是mongoDB,而node调用mongoDB也是很方便的。

  

    • 三大基础能力支持:
      • 云数据库:是一个JSON数据库(文档型数据库),提供了2GB的免费存储空间,实现对数据的增删改查的操作;
        • 支持的数据类型:Number、String、Object、Array、Boolean、Date、Null以及GeoPoint(地理位置点);
        • 如何通过代码操作数据库:
          • 初始化:
            const db = wx.cloud.database()
          • 切换环境
            const testDB = wx.cloud.database({
              env: 'test'//环境名称
            })
          • 简单数据的增删改查
            • WXML
              <view>数据库的增删改查</view>
              <button size="mini" catchtap="onCatchPostHandler">增加</button>
              <button size="mini" catchtap="onCatchDeleteHandler">删除</button>
              <button size="mini" catchtap="onCatchUpdateHandler">修改</button>
              <button size="mini" catchtap="onCatchGetHandler">查找</button>
              View Code
            • JS
              // 数据库的初始化
              const db = wx.cloud.database();
              
              Page({
              
                /**
                 * 页面的初始数据
                 */
                data: {
              
                },
                /**
                 * 数据库的添加
                 */
                onCatchPostHandler() {
                  // 回调函数写法
                  /**
                   * db.collection('user').add({
                    data: {
                      name: 'wxh',
                      age: '18',
                      job: 'IT'
                    },
                    success: (res) => {
                      // 使用了ES6中的箭头函数,目的是为了改变this指向
                      console.log(res)
                    },
                    fail: (error) => {
                      console.log(error)
                    }
                  })
                   */
                  // promise的写法
                  db.collection('user')
                    .add({
                      data: {
                        name: 'jerry',
                        age: '22',
                        job: 'teacher'
                      }
                    })
                    .then((res) => {
                      console.log(res)
                    })
                    .catch((error) => {
                      console.log(error)
                    })
                },
                /**
                 * 数据库的删除
                 */
                onCatchDeleteHandler() {
                  // 删除一条可以通过小程序端进行控制,而删除多条我们需要小程序调用云函数来操作数据库
                  db.collection('user')
                    .doc("b040a67a5df1f6d1029170ef7e785160")
                    .remove()
                    .then((res) => {
                      console.log(res)
                    })
                    .catch((error) => {
                      console.log(error)
                    })
                },
                /**
                 * 数据库的修改
                 */
                onCatchUpdateHandler() {
                  db.collection('user')
                    .doc('b040a67a5df1f6d1029170ef7e785160')
                    .update({
                      data: {
                        age: '19'
                      }
                    })
                    .then((res) => {
                      console.log(res)
                    })
                    .catch((error) => {
                      console.log(error)
                    })
                },
                /**
                 * 数据库的查找
                 */
                onCatchGetHandler() {
                  db.collection('user')
                    .where({
                      name: 'wxh'
                    })
                    .get({})
                    .then((res) => {
                      console.log(res)
                    })
                    .catch((error) => {
                      console.log(error)
                    })
                },
              View Code
            • 注意:如果是在数据库手动加入记录,会出现查不到的情况,这个时候我们需要设置

                                                             

      • 云函数:相当于小程序在服务端的后台代码,可以非常方便的获取到当前登录用户的信息(appid、openid、生成分享图或者调用腾讯云的SDK);
        • 去Node官网(http://nodejs.cn/),安装Node环境(需要nodev8.0及以上版本);
        • 安装成功的标志:windows+r,输入cmd, 打开命令输入  node -v 显示版本号;

                                          

        •  创建云函数

                                          

          • 很有可能提醒是否需要安装wx-server-sdk    ----- >    点击确定;
          • 每次修改云函数都需右键点击“上传并部署,云端安装依赖”
          • 在调用云函数的过程中提示没有安装wx-server-sdk包,这个时候在cloudfunctions中,右键在终端打开,输入安装命令npm install --save wx-server-sdk@latest(表示安装最新版本)
        • 简单的调用一个云函数:求a+b的和;
          • sum下的index.js
            // 云函数入口函数
            exports.main = async (event, context) => {
              // event 中包括小程序调用云函数传过来的对象
              // context 指当前调用的上下文,同时也包括当前用户的一些信息
              return {
                sum: event.a + event.b
              }
            }
          • <button catchtap="onCatchSumHandler" size="mini">调用云函数sum</button>
              /**
              * 云函数的调用
              */
              onCatchSumHandler() {
                wx.cloud
                  .callFunction({
                    name: 'sum',//当前云函数的名称
                    data: {
                      a: 2,
                      b: 3
                    }
                  })
                  .then((res) => {
                    console.log(res)
                  })
                  .catch(error => {
                    console.log(error)
                  })
              },
            View Code
        • 获取当前用户的openid:
          • 传统的微信登录方式与小程序云开发登录方式的区别:
            • 传统的微信登录方式
                  首先用户端小程序通过调用wx.login,从微信服务端获取一个code,然后用户小程序端调用wx.request将code传递给后端服务器,后端
              获得到code之后,对微信服务端发起请求,通过code获取openid与session_key,最后将小程序的唯一标识发送给小程序本地存储。

            • 小程序云开发登录方式
                  用户通过点击按钮,从小程序获取用户的信息,而小程序通过云函数获得用户的信息,云函数给小程序端返回用户的openid,小程序获取到
              用户的信息之后,将用户的信息存储到云数据库。

          • 云函数会自带一个login文件夹,它的作用就是获取当前用户的信息;
            <button catchtap="onCatchOpenIdHandler" size="mini">获取当前用户openid</button>
            
              /**
              * 获取当前用户的openid
              */
              onCatchOpenIdHandler() {
                wx.cloud
                  .callFunction({
                    name: 'login',
                  })
                  .then((res) => {
                    console.log(res)
                  })
                  .catch((error) => {
                    console.log(error)
                  })
              },
            View Code
        • 批量删除
          • 定义云函数batchDelete
            // 云函数入口文件
            const cloud = require('wx-server-sdk')
            
            cloud.init()
            
            // 获取云数据库
            const db = cloud.database();
            
            // 云函数入口函数
            exports.main = async (event, context) => {
              // 数据库是一个异步的操作,等到删除成功或者失败才可以返回数据给小程序  因此需要ES7的await
              try {
                return await db.collection('user')
                  .where({
                    name: event.name
                  })
                  .remove();
              }
              catch (error) {
                console.log(error)
              }
            }
            View Code
          • 调用云函数
            <button catchtap="onCatchBatchDeleteIdHandler" size="mini">批量删除数据</button>
            
            
              /**
              * 批量删除
              */
              onCatchBatchDeleteIdHandler() {
                wx.cloud.callFunction({
                  name: 'batchDelete',
                  data: {
                    name: 'wxh'
                  }
                }).then((res) => {
                  console.log(res)
                }).catch((error) => {
                  console.log(error)
                })
              },
            View Code
      • 云存储:管理、上传、下载以及分享文件等操作;
        • 云存储能力
          • wx.cloud.uploadFile  -----   上传文件
            • 步骤示意图

                                                            

            • 上传并展示的代码
              <view>云存储</view>
              <button catchtap="onCatchUploadHandler">上传图片</button>
              <button catchtap="onCatchShowHandler">展示图片</button>
              <view wx:for="{{showImgPath}}" wx:key="index">
              <image src="{{item.fileID}}"></image>
              </view>
              
              
              
              
                /**
                 * 页面的初始数据
                 */
                data: {
                  showImgPath: []
                },
                /**
                 * 图片上传
                 */
                onCatchUploadHandler() {
                  // 1、从本地相册选择图片或使用相机拍照
                  wx.chooseImage({
                    count: 1, //最多选择的图片张数,最大值为9
                    sizeType: ['original', 'compressed'], //所选图片的尺寸(原图、压缩)
                    sourceType: ['album', 'camera'], //图片来源(相册、相机),电脑端只会打开相册,而手机端会有两个选项(拍照或者相册)
                    success(res) {
                      // tempFilePath可以作为img标签的src属性显示图片
                      const tempFilePaths = res.tempFilePaths[0];
                      wx.cloud.uploadFile({
                        cloudPath: new Date().getTime() + 'png', // 上传至云端的路径  可以指定文件夹以及文件名称  如果写死每次上传都会覆盖原有图片
                        filePath: tempFilePaths, // 小程序临时文件路径
                        success: res => {
                          console.log("上传成功")
                          // 返回文件 ID
                          db.collection('imgFile')
                            .add({
                              data: {
                                fileID: res.fileID
                              },
                              success: (res) => {
                                console.log(res)
                                console.log("保存成功")
                              },
                              fail: (error) => {
                                console.log(error)
                              }
                            })
                        },
                        fail: console.error
                      })
                    }
                  })
                },
                /**
                 * 图片展示
                 */
                onCatchShowHandler() {
                  // 1、通过云存储查找用户本人管理的图片
                  wx.cloud.callFunction({
                    name: 'login',
                    success: res => {
                      const openid = res.result.openid;
                      // 2、去数据库中查找
                      db.collection('imgFile')
                        .where({
                          _openid: openid
                        })
                        .get()
                        .then((res) => {
                          this.setData({
                            showImgPath: res.data
                          })
                          console.log(res)
                        })
                        .catch((error) => {
                          console.log(error)
                        })
                    },
                    fail: error => {
                      console.log(error)
                    }
                  })
                },
              View Code
            • 上传多张图片
              • WXML
                 <!-- 评价 -->
                  <view class="comment-container">
                    <van-field value="{{ content }}" placeholder="写一些评价吧" bind:change="onContentChange" />
                    <van-rate value="{{ score }}" bind:change="onScoreChange" />
                    <view style="margin-bottom:20rpx">
                      <van-button type="warning" bindtap="uploadImg" size="small">上传图片</van-button>
                    </view>
                    <view>
                      <image class="comment-img" src="{{item}}" wx:for="{{uploadImages}}" wx:key="index"></image>
                    </view>
                    <van-button size="large" type="danger" bindtap="submit">提交评价</van-button>
                  </view>
                </view>
                View Code
              • JS

                // 对数据库进行初始化
                const db = wx.cloud.database();
                
                Page({
                
                  /**
                   * 页面的初始数据
                   */
                  data: {
                    movieid: '', //对应电影的movieid
                    movieDetail: {},
                    content: '', //评价的内容
                    score: 5, //电影评分
                    uploadImages: [], //上传的图片
                    fileIds: [], //云存储返回的图片id
                  },
                
                  /**
                   * 生命周期函数--监听页面加载
                   */
                  onLoad: function(options) {
                    // 获取上一个页面传过来的参数
                    this.setData({
                      movieid: options.movieid
                    })
                    this.getMovieDetail(options.movieid)
                  },
                  /**
                   * 获取电影详情信息
                   */
                  getMovieDetail(movieid) {
                    wx.showLoading({
                      title: '加载中',
                    })
                    wx.cloud.callFunction({
                      name: 'getDetail',
                      data: {
                        movieid: movieid
                      },
                      success: res => {
                        this.setData({
                          movieDetail: JSON.parse(res.result)
                        })
                        wx.hideLoading()
                      },
                      fail: error => {
                        console.log(error)
                      }
                    })
                  },
                  /**
                   * 输入评价
                   */
                  onContentChange(event) {
                    this.setData({
                      content: event.detail //输入框的内容
                    })
                  },
                  /**
                   * 进行评分
                   */
                  onScoreChange(event) {
                    this.setData({
                      score: event.detail
                    });
                  },
                  /**
                   * 上传图片
                   */
                  uploadImg() {
                    wx.chooseImage({
                      count: 3,
                      sizeType: ['original', 'compressed'],
                      sourceType: ['album', 'camera'],
                      success: res => { //可以改变this指向
                        // tempFilePath可以作为img标签的src属性显示图片
                        const tempFilePaths = res.tempFilePaths;
                        this.setData({
                          uploadImages: this.data.uploadImages.concat(tempFilePaths)
                        })
                      }
                    })
                  },
                  /**
                   * 提交评价
                   */
                  submit() {
                    wx.showLoading({
                      title: '评价中...',
                    })
                    // 首先获取到评价的内容  分数  以及上传的图片
                    // 涉及到了异步(非阻塞)的问题,由于上传时间不确定,因此需要成功上传到云存储才能将fileid存到云数据库
                    let promiseArr = [];
                    // 1、上传图片到云存储
                    for (let i = 0; i < this.data.uploadImages.length; i++) {
                      promiseArr.push(new Promise((resolve, reject) => {
                        let item = this.data.uploadImages[i];
                        // 通过正则表达式取出文件对应的扩展名
                        let suffix = /\.\w+$/.exec(item)[0];
                        wx.cloud.uploadFile({
                          cloudPath: new Date().getTime() + suffix, // 上传至云端的路径
                          filePath: item, // 小程序临时文件路径
                          success: res => {
                            // 返回文件 ID
                            this.setData({
                              fileIds: this.data.fileIds.concat(res.fileID)
                            });
                            resolve()
                          },
                          fail: console.error
                        })
                      }))
                    }
                    Promise.all(promiseArr).then((res) => {
                      // 2、插入数据
                      db.collection('comment').add({
                        data: {
                          content: this.data.content,
                          score: this.data.score,
                          movieid: this.data.movieid,
                          fileIds: this.data.fileIds
                        },
                        success: (res) => {
                          wx.showToast({
                            title: '评价成功',
                          });
                          wx.hideLoading()
                        },
                        fail: (error) => {
                          wx.hideLoading();
                          wx.showToast({
                            title: '评价失败',
                          })
                        }
                      })
                
                    }).catch((error) => {
                      console.log(error)
                    })
                  },
                View Code
              • 效果图

                                                                         

 

 

          • wx.cloud.downloadFile  -----   下载文件
            • 步骤示意图

                                                           

            • 代码
              • WXML
                <view>云存储</view>
                <button catchtap="onCatchUploadHandler">上传图片</button>
                <button catchtap="onCatchShowHandler">展示图片</button>
                <button catchtap="onCatchSettingAgainHandler">再次调起配置页</button>
                <view wx:for="{{showImgPath}}" wx:key="index">
                  <image src="{{item.fileID}}"></image>
                  <button catchtap="onCatchDownLoadHandler" data-fileID="{{item.fileID}}">下载图片</button>
                </view>
                View Code
              • JS
                  /**
                   * 图片下载
                   */
                  onCatchDownLoadHandler(event) {
                    const fileID = event.target.dataset.fileid;
                    wx.cloud.downloadFile({
                      fileID: fileID,
                      success: res => {
                        wx.showToast({
                          title: '下载成功',
                        })
                        // 保存到手机相册
                        wx.saveImageToPhotosAlbum({
                          filePath: res.tempFilePath,
                          success: (res) => {
                            wx.showToast({
                              title: '保存成功',
                            })
                          },
                          fail: (error) => {
                            if (error.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || error.errMsg === "saveImageToPhotosAlbum:fail auth deny" || error.errMsg === "saveImageToPhotosAlbum:fail authorize no response") {
                              wx.showToast({
                                title: '用户拒绝了',
                              });
                              wx.openSetting({
                                success: res => {
                                  console.log(res)
                                  if (res.authSetting['scope.writePhotosAlbum']) {
                                    wx.showModal({
                                      title: '提示',
                                      content: '获取权限成功,再次点击图片即可保存',
                                      showCancel: false,
                                    })
                                  } else {
                                    wx.showModal({
                                      title: '提示',
                                      content: '获取权限失败,将无法保存到相册哦~',
                                      showCancel: false,
                                    })
                                  }
                                },
                                fail: error => {
                                  console.log(error)
                                }
                              })
                            }
                          }
                        })
                      },
                      fail: error => {
                        console.log(error)
                      }
                    })
                  },
                  /**
                   * 打开配置
                   */
                  onCatchSettingAgainHandler() {
                    wx.openSetting({
                      success: res => {
                        console.log(res)
                      },
                      fail: error => {
                        console.log(error)
                      }
                    })
                  },
                View Code
          • wx.cloud.deleteFile  -----   删除文件
          • wx.cloud.getTempFileURL  -----   获取临时链接

3、云开发的开通

  • 打开微信开发工具,点击云开发 -----> 开通 -----> 确定

     

  • 会出现一个环境配置,每个小程序账号可免费创建两个环境,建议是一、开发环境;二、生产环境;
    • 注意:开发工具右上角点击 “详情” -----> 本地设置(调试基础库的版本必须在2.2.3以上,才可以支持云开发)
  • 云开发提供了一个可视化的控制台,点击云开发即可出现;

4、遇到的问题

posted @ 2019-12-12 17:47  北栀女孩儿  阅读(947)  评论(0编辑  收藏  举报