微信小程序云开发之简单数据增删改查案例

微信小程序简单数据增删改查案例

微信小程序云开发提供了一个 JSON 数据库,顾名思义,数据库中的每条记录都是一个 JSON 格式的对象。一个数据库可以有多个集合(相当于关系型数据中的表),集合可看做一个 JSON 数组,数组中的每个对象就是一条记录,记录的格式是 JSON 对象。
关系型数据库和 JSON 数据库的概念对应关系如下表:

关系型 文档型
数据库 database 数据库 database
表 table 集合 collection
行 row 记录 record / doc
列 column 字段 field

先看效果图,微信小程序搜索陌然 Tool或者微信扫描下面二维码可以观看更多教程:

小程序二维码
微信小程序云开发之简单数据增删改查案例_第1张图片

运行效果图

微信小程序云开发之简单数据增删改查案例_第2张图片
微信小程序云开发之简单数据增删改查案例_第3张图片
微信小程序云开发之简单数据增删改查案例_第4张图片
微信小程序云开发之简单数据增删改查案例_第5张图片

案例源代码

部分样式我放在app.wxss文件中就没有写出来,样式可以自己美化,每个人审美标准不一样。

Page({

  /**
   * 页面的初始数据
   */
  data: {
    openid: "", // 用户身份ID
    opName: "", // 数据库操作名称,如‘add’‘qry’等等
    opResult: "", // 数据库操作结果字符串
    opResult2: "", // 数据库操作结果字符串2
    resData: null, // 数据库操作结果数据
    resData2: null, // 数据库操作结果数据2
    finished: false // 数据库操作是否完成的标记
  },
  // “增”按钮点击事件函数
  addRecord: function() {
    this.setData({
      opName: "add",
      finished: false
    })
  },
  // “删”按钮点击事件函数
  deleteRecord: function() {
    this.setData({
      opName: "del",
      finished: false
    })
  },
  // “改”按钮点击事件函数
  updateRecord: function() {
    this.setData({
      opName: "upd",
      finished: false
    })
  },
  // “查”按钮点击事件函数
  queryRecord: function() {
    this.setData({
      opName: "qry",
      finished: false
    })
  },
  // 拼接日期字符串的函数
  makeDateString: function(dateObj) {
    return dateObj.getFullYear() + '-' + (dateObj.getMonth() + 1) + '-' + dateObj.getDate();
  },
  // 拼接时间字符串的函数
  makeTimeString: function(dateObj) {
    return dateObj.getHours() + ':' + dateObj.getMinutes() + ':' + dateObj.getSeconds();
  },
  // 添加记录事件函数
  doAdd: function(e) {
    console.log(e)
    var workContent = e.detail.value.workContent
    if (workContent != "") { // 如果用户输入内容不为空
      const db = wx.cloud.database() // 调用接口返回云开发数据库引用保存在常量db中
      var myDate = new Date()
      db.collection('work_done').add({ // 向集合‘work_done’中添加一条记录
        data: { // 一条记录的字段数据
          date: this.makeDateString(myDate), // 日期字符串
          time: this.makeTimeString(myDate), // 时间字符串
          content: workContent // 工作内容字符串
        },
        complete: res => { // 操作完成时的回调函数
          this.setData({
            finished: true
          })
        },
        success: res => { // 操作成功时的回调函数
          // 在返回结果中会包含新创建的记录的 _id
          this.setData({
            opResult: "操作完成,新增一条记录,_id为:\n ",
            resData: res._id
          })
          wx.showToast({
            title: '新增记录成功',
          })
          console.log('[数据库] [新增记录] 成功,记录 _id: ', res._id)
        },
        fail: err => { // 操作失败时的回调函数
          wx.showToast({
            icon: 'none',
            title: '新增记录失败'
          })
          console.error('[数据库] [新增记录] 失败:', err)
        }
      })
    } else {
      wx.showToast({
        title: '请输入事情描述!',
      })
    }
  },
  // 删除记录事件函数
  doDelete: function(e) {
    console.log(e)
    var that = this
    var itemID = e.detail.value.itemID
    if (itemID != "") { // 如果用户输入的记录id不为空
      const db = wx.cloud.database() // 调用接口返回云开发数据库引用保存在常量db中
      db.collection('work_done').doc(itemID).get({ // 从集合‘work_done’中查询id为itemID的记录
        success: res => { // 操作成功时的回调函数
          console.log(res)
          this.setData({
            opResult: '查询记录成功:\n',
            resData: res.data
          })
          db.collection('work_done').doc(itemID).remove({ // 操作接口从集合‘work_done’中删除这条记录
            complete: res => { // 操作完成时的回调函数
              that.setData({
                finished: true
              })
            },
            success: res => { // 操作成功时的回调函数
              console.log('[数据库] [删除记录] 成功: ', res)
              that.setData({
                opResult2: '已成功删除上面的记录。'
              })
            },
            fail: err => { // 操作失败时的回调函数
              wx.showToast({
                icon: 'none',
                title: '删除记录失败'
              })
              console.error('[数据库] [删除记录] 失败:', err)
            }
          })
        },
        fail: err => { // 操作失败时的回调函数
          wx.showToast({
            icon: 'none',
            title: '查询记录失败'
          })
          console.error('[数据库] [查询记录] 失败:', err)
        }
      })
    } else {
      wx.showToast({
        title: '请输入itemID!',
      })
    }
  },
  // 更新记录事件函数
  doUpdate: function(e) {
    console.log(e)
    var that = this
    var itemID = e.detail.value.itemID
    var workContent = e.detail.value.workContent
    if (itemID != "") { // 如果用户输入的记录id不为空
      const db = wx.cloud.database() // 调用接口返回云开发数据库引用保存在常量db中
      db.collection('work_done').doc(itemID).get({ // 从集合‘work_done’中查询id为itemID的记录
        success: res => { // 操作成功时的回调函数
          this.setData({
            opResult: '查询记录成功:\n',
            resData: res.data
          })
          db.collection('work_done').doc(itemID).update({ // 更新集合‘work_done’中的这条记录
            data: {
              content: workContent,
            },
            complete: res => { // 操作完成时的回调函数
              that.setData({
                finished: true
              })
            },
            success: res => { // 操作成功时的回调函数
              console.log('[数据库] [更新记录] 成功: ', res)
              that.setData({
                opResult2: '已成功更新上面的记录内容为:\n',
                resData2: workContent
              })
            },
            fail: err => { // 操作失败时的回调函数
              wx.showToast({
                icon: 'none',
                title: '更新记录失败'
              })
              console.error('[数据库] [更新记录] 失败:', err)
            }
          })
        },
        fail: err => { // 操作失败时的回调函数
          wx.showToast({
            icon: 'none',
            title: '查询记录失败'
          })
          console.error('[数据库] [查询记录] 失败:', err)
        }
      })
    } else {
      wx.showToast({
        title: '请输入itemID!',
      })
    }
  },
  // 查询记录事件函数
  doQuery: function(e) {
    console.log(e)
    var workDate = e.detail.value.workDate
    if (workDate != "") { // 如果用户输入的日期字符串不为空
      const db = wx.cloud.database() // 调用接口返回云开发数据库引用保存在常量db中
      db.collection('work_done').where({ // 从集合‘work_done’中查询记录(最多二十条)
        date: workDate // 记录创建日期
      }).get({
        complete: res => { // 操作完成时的回调函数
          this.setData({
            finished: true
          })
        },
        success: res => { // 操作成功时的回调函数
          this.setData({
            opResult: "操作完成,查询到" + res.data.length + "条记录:\n ",
            resData: res.data
          })
          console.log('[数据库] [查询记录] 成功: ', res)
        },
        fail: err => { // 操作失败时的回调函数
          wx.showToast({
            icon: 'none',
            title: '查询记录失败'
          })
          console.error('[数据库] [查询记录] 失败:', err)
        }
      })
    } else {
      wx.showToast({
        title: '请输入查询日期!',
      })
    }
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    this.setData({
			openid: wx.getStorageSync('openID') // 读取本地存储的openID(“获取OpenID”案例中同步存储了用户的openid到本地)
    });
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function() {

  }
})
<!--pages/cloud/Database/index.wxml-->
<view class="box">
  <view class='title'>数据库操作</view>
  <text class="preNote">请点击相应按钮,实现在数据库中增加、删除、更新或查询记录的操作</text>
  <view class="Hcontainer">
    <button class='DBbutton' bindtap="addRecord" style='background-color: {{opName=="add"?"#ae57a4":"blue"}}'></button>
    <button class='DBbutton' bindtap="deleteRecord" style='background-color: {{opName=="del"?"#ae57a4":"blue"}}'></button>
    <button class='DBbutton' bindtap="updateRecord" style='background-color: {{opName=="upd"?"#ae57a4":"blue"}}'></button>
    <button class='DBbutton' bindtap="queryRecord" style='background-color: {{opName=="qry"?"#ae57a4":"blue"}}'></button>
  </view>
  <view wx:if="{{opName=='add'}}">
    <!-- 新增记录 -->
    <view class="record-op" style='{{opName!=""?"border: 1px solid #00007f":""}}'>
      <form bindsubmit='doAdd'>
        <text class="op-note">添加一件今日已完成的工作:</text>
        <textarea name="workContent" class="content-input" maxlength="50" placeholder="事情描述(不超过50个字)" auto-height adjust-position cursor-spacing='20px'></textarea>
        <button form-type='submit' type='primary'>确定</button>
      </form>
    </view>
    <view wx:if="{{finished}}" class="op-result">
      <text class="headline">操作结果信息:</text>
      <text class='text-title'>{{opResult}}</text>
      <text class="list" selectable>{{resData}}</text>
    </view>
  </view>
  <view wx:if="{{opName=='del'}}">
    <!-- 删除记录 -->
    <view class="record-op" style='{{opName!=""?"border: 1px solid #00007f":""}}'>
      <form bindsubmit='doDelete'>
        <text class="op-note">指定删除item的ID:</text>
        <input name="itemID" class="line-input" maxlength="32" placeholder="itemID(32位字符串)" />
        <button form-type='submit' type='primary'>确定</button>
      </form>
    </view>
    <view wx:if="{{finished}}" class="op-result">
      <text class="headline">操作结果信息:</text>
      <text class='text-title'>{{opResult}}</text>
      <text class="list" selectable>{{resData._id}}{{resData.date}} {{resData.time}} {{resData.content}}</text>
      <text class='text-title'>{{opResult2}}</text>
    </view>
  </view>
  <view wx:if="{{opName=='upd'}}">
    <!-- 更新记录 -->
    <view class="record-op" style='{{opName!=""?"border: 1px solid #00007f":""}}'>
      <form bindsubmit='doUpdate'>
        <text class="op-note">指定更新item的ID:</text>
        <input name="itemID" class="line-input" maxlength="32" placeholder="itemID(32位字符串)" />
        <text class="op-note">输入更新的内容:</text>
        <textarea name="workContent" class="content-input" maxlength="50" placeholder="事情描述(不超过50个字)" auto-height adjust-position cursor-spacing='20px'></textarea>
        <button form-type='submit' type='primary'>确定</button>
      </form>
    </view>
    <view wx:if="{{finished}}" class="op-result">
      <text class="headline">操作结果信息:</text>
      <text class='text-title'>{{opResult}}</text>
      <text class="list" selectable>{{resData._id}}{{resData.date}} {{resData.time}} {{resData.content}}</text>
      <text class='text-title'>{{opResult2}}</text>
      <text class="list" selectable>{{resData2}}</text>
    </view>
  </view>
  <view wx:if="{{opName == 'qry'}}">
    <!-- 查询记录 -->
    <view class="record-op" style='{{opName!=""?"border: 1px solid #00007f":""}}'>
      <form bindsubmit='doQuery'>
        <text class="op-note">指定查询日期(年-月-日,不需要无效的0):</text>
        <input name="workDate" class="line-input" maxlength="10" placeholder="事件日期(年-月-日)" />
        <button form-type='submit' type='primary'>确定</button>
      </form>
    </view>
    <view wx:if="{{finished}}" class="op-result">
      <text class="headline">操作结果信息:</text>
      <text class='text-title'>{{opResult}}</text>
      <block wx:for='{{resData}}' wx:key='{{item._id}}'>
        <text class="list" selectable>{{item._id}}{{item.date}} {{item.time}} {{item.content}}</text>
      </block>
    </view>
  </view>
</view>
/* pages/cloud/Database/index.wxss */

.preNote {
  padding: 20px;
  font-size: 32rpx;
  line-height: 40rpx;
  color: #666;
  box-sizing: border-box;
}

.Hcontainer {
  margin: 20rpx 0rpx;
  padding: 0 50rpx;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}

.DBbutton {
  width: 100rpx;
  color: white;
  background-color: #0066ff;
}

.record-op {
  margin: 10rpx;
  padding: 20rpx;
  box-sizing: border-box;
}

.op-note {
  color: #000;
  font-size: 14px;
}

.content-input {
  width: 90%;
  padding: 20rpx;
  margin: 20rpx;
  min-height: 200rpx;
  border: 1px solid #ccc;
  box-sizing: border-box;
}

.op-result {
  padding: 10rpx;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}

.op-result .headline {
  margin-top: 50rpx;
  font-size: 40rpx;
  font-weight: bold;
  color: #0066ff;
}

.op-result .text-title {
  margin-top: 20rpx;
  margin-bottom: 10rpx;
  padding-left: 20rpx;
  padding-right: 20rpx;
  font-size: 14px;
  color: red;
}

.op-result .list {
  margin-top: 20rpx;
  font-size: 28rpx;
  color: black;
  display: block;
}

.line-input {
  min-height: 30px;
  line-height: 20px;
  width: 100%;
  padding: 5px;
  margin: 10px 0;
  display: inline-block;
  border: 1px solid #ccc;
  border-radius: 5px;
  box-sizing: border-box;
}

云开发数据库提供以下几种数据类型:

  • String:字符串
  • Number:数字
  • Object:对象
  • Array:数组
  • Bool:布尔值
  • Date:时间
  • Geo:多种地理位置类型,详见下
  • Null:相当于一个占位符,表示一个字段存在但是值为空。

下面对Data的字段做下补充说明。

Date

Date 类型用于表示时间,精确到毫秒,在小程序端可用 JavaScript 内置 Date 对象创建。需要特别注意的是,在小程序端创建的时间是客户端时间,不是服务端时间,这意味着在小程序端的时间与服务端时间不一定吻合,如果需要使用服务端时间,应该用 API 中提供的 serverDate 对象来创建一个服务端当前时间的标记,当使用了 serverDate 对象的请求抵达服务端处理时,该字段会被转换成服务端当前的时间,更棒的是,我们在构造 serverDate 对象时还可通过传入一个有 offset 字段的对象来标记一个与当前服务端时间偏移 offset 毫秒的时间,这样我们就可以达到比如如下效果:指定一个字段为服务端时间往后一个小时。

那么当我们需要使用客户端时间时,存放 Date 对象和存放毫秒数是否是一样的效果呢?不是的,我们的数据库有针对日期类型的优化,建议大家使用时都用 Date 或 serverDate 构造时间对象。

以下是一个示例的集合数据,假设我们有一个 books 集合存放了图书记录,其中有两本书:

[
  {
    "_id": "Wzh76lk5_O_dt0vO",
    "title": "The Catcher in the Rye",
    "author": "J. D. Salinger",
    "characters": [
      "Holden Caulfield",
      "Stradlater",
      "Mr. Antolini"
    ],
    "publishInfo": {
      "year": 2019,
      "country": "United States"
    }
  },
  {
    "_id": "Wzia0lk5_O_dt0vR",
    "_openid": "ohl4L0Rnhq7vmmbT_DaNQa4ePaz0",
    "title": "The Lady of the Camellias",
    "author": "Alexandre Dumas fils",
    "characters": [
      "Marguerite Gautier",
      "Armand Duval",
      "Prudence",
      "Count de Varville"
    ],
    "publishInfo": {
      "year": 1998,
      "country": "France"
    }
  }
]

在图书信息中,我们用 title, author 来记录图书标题和作者,用 characters 数组来记录书中的主要人物,用 publishInfo 来记录图书的出版信息。在其中我们可以看到,字段既可以是字符串或数字,还可以是对象或数组,就是一个 JSON 对象。

每条记录都有一个 _id 字段用以唯一标志一条记录、一个 _openid 字段用以标志记录的创建者,即小程序的用户。需要特别注意的是,在管理端(控制台和云函数)中创建的不会有 _openid 字段,因为这是属于管理员创建的记录。开发者可以自定义 _id,但不可自定义和修改 _openid 。_openid 是在文档创建时由系统根据小程序用户默认创建的,开发者可使用其来标识和定位文档。

数据库 API 分为小程序端和服务端两部分,小程序端 API 拥有严格的调用权限控制,开发者可在小程序内直接调用 API 进行非敏感数据的操作。对于有更高安全要求的数据,可在云函数内通过服务端 API 进行操作。云函数的环境是与客户端完全隔离的,在云函数上可以私密且安全的操作数据库。

数据库 API 包含增删改查的能力,使用 API 操作数据库只需三步:获取数据库引用、构造查询/更新条件、发出请求。以下是一个在小程序中查询数据库的发表于美国的图书记录的例子:

// 1. 获取数据库引用
const db = wx.cloud.database()
// 2. 构造查询语句
// collection 方法获取一个集合的引用
// where 方法传入一个对象,数据库返回集合中字段等于指定值的 JSON 文档。API 也支持高级的查询条件(比如大于、小于、in 等),具体见文档查看支持列表
// get 方法会触发网络请求,往数据库取数据
db.collection('books').where({
  publishInfo: {
    country: 'United States'
  }
}).get({
  success: function(res) {
  // 输出 [{ "title": "The Catcher in the Rye", ... }]
  console.log(res)
 }
})

你可能感兴趣的:(微信小程序云开发)