微信小程序雲開發之簡單數據增刪改查案例

微信小程序簡單數據增刪改查案例

微信小程序雲開發提供了一個 JSON 數據庫,顧名思義,數據庫中的每條記錄都是一個 JSON 格式的對象。一個數據庫可以有多個集合(相當於關係型數據中的表),集合可看做一個 JSON 數組,數組中的每個對象就是一條記錄,記錄的格式是 JSON 對象。
關係型數據庫和 JSON 數據庫的概念對應關係如下表:

關係型 文檔型
數據庫 database 數據庫 database
表 table 集合 collection
行 row 記錄 record / doc
列 column 字段 field

先看效果圖,微信小程序搜索陌然 Tool或者微信掃描下面二維碼可以觀看更多教程:

小程序二維碼
在這裏插入圖片描述

運行效果圖

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

案例源代碼

部分樣式我放在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)
 }
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章