由於小程序本身存儲數據的能力有限,所以不可能將大量的數據保存在客戶端,而且將數據保存在本地既不安全,也無法與其他小程序用戶共享,所以大多數小程序都需要一個服務端,服務端可以用多種技術實現,如 PHP、Node.js、Python、Asp.net、Java EE 等。不管使用哪種技術實現服務端,開發一款小程序都需要至少配備兩個程序員,一個是開發小程序的程序員,一個是開發服務端的程序員;而且這兩個程序員之間還需要不斷溝通,以便確認共同遵循的接口。
開發一款小程序需要兩名或更多的程序員參與,一直困擾着很多小的創業公司,因為多雇佣一個人,就會增加很多成本。所以基於這個痛點,很多公司推出了雲開發技術,例如 Bmob 就是較早推出雲開發的公司,所謂雲開發,就是將服務端的功能都封裝起來,然后向客戶端提供 API 訪問這些封裝的功能。服務端的主要功能無外乎數據存儲、文件上傳下載、視頻/音頻流等功能。這些功能大多開發都不困難,但比較費時,所以將其封裝起來供客戶端調用是一個非常好的主意。
騰訊最近推出了自己的雲開發系統,不過這個雲開發系統目前只能用於小程序,而且只提供了如下三種:
- 雲數據庫
- 雲存儲
- 雲函數
雲數據庫是指在服務端提供的數據庫服務,小程序雲提供的數據庫屬於文檔數據庫,文檔數據庫有別於關系型數據庫。傳統的關系型數據庫中可以保存若干個表,每一個表由若干條記錄組成。但文檔數據庫保存的是 JSON 格式的數據,每一個 JSON 文檔相當於關系型數據庫中的一個表。也就是說,文檔數據庫保存的是 JSON 文檔的集合。非常流行的 MongoDB 就是典型的文檔數據庫。雲數據庫個組成部分對應的關系如下表所示。
| 關系數據庫 | 文檔數據庫 |
|---|---|
| 數據庫(DataBase) | 數據庫(DataBase) |
| 表(table) | 集合(collection) |
| 行(row) | 記錄(record/doc) |
| 列(column) | 字段(field) |
雲存儲為小程序提供了遠程上傳和下載文件的能力。下載可以提供權限管理,小程序可以通過相應的 API 實現文件的上傳和下載功能。
雲函數就是一段可以運行在服務端的代碼,之所以要將部分代碼在服務端運行,主要有如下兩個原因:
- 部署多個用戶共享,且容易維護的代碼
- 獲取敏感信息,如 AppID、OpenID 等
搭建雲開發環境
現在讓我們來開發第一個與雲的小程序,首先應該下載最新版的微信開發者工具,然后在小程序后台獲取 AppID。使用雲開發功能,必須使用真實的 AppID,不能使用測試用的 AppID。
啟動微信開發者工具,新創建一個小程序工程。在創建小程序工程的過程中,需要輸入 AppID 和項目名稱,然后在最下面的目標列表中選擇“建立雲開發快速啟動模板”選項,如下圖所示。

創建完支持雲開發的小程序工程后,工程目錄結構和 IDE 主界面如下圖所示。當前工程默認帶了一些例子(模板中的例子)來幫助理解和開發基於雲的小程序。

如果第一次使用這個 AppID 開發基於雲的小程序,應該單擊界面上方的“雲開發”按鈕,會顯示如下圖所示的頁面。

這是一個開通雲服務的頁面,單擊“開通”按鈕,就會開通用於雲開發的服務。在開通的過程中會出現如下圖所示的確認對話框,單擊”確定“按鈕進入下一個設置頁面。

這個頁面是”新建環境“頁面,如下圖所示。需要輸入“環境名稱”,一個任意的字符串。在下面列出了基礎版的配置,如數據庫存儲空空間、雲函數數量等。如果想要更多的資源,那以后肯定是要收費的,天下沒有免費的午餐。不過這個配置做實驗和用戶量不是非常大的小程序還是夠用的。

單擊“確定”按鈕,創建一個環境,然后進入如下圖所示的雲開發控制台。在這個控制台中可以管理用戶、雲數據庫、雲存儲、雲函數及統計分析,並且會顯示相關的信息,如今日 API 調用:

如果想創建新環境,可以將鼠標放在右側當前環境 minicloud 上,會彈出如下圖所示的菜單,單擊”創建新環境“菜單項則會創建一個新的環境,目前每個小程序賬號課免費創建兩個新環境。

部署 login 雲函數
模板會默認創建一個 login 雲函數,用於返回 OpenID(標識當前微信登錄用戶的 ID),所以在開發基於雲的小程序之前,首先要先部署 login 雲函數。
選中 login 雲函數,在右鍵菜單中單擊“上傳並部署”菜單項進行部署,如下圖所示。

成功部署 login 雲函數后,回到小程序的主頁面,單擊“點擊獲取 openid”按鈕,如圖所示,則會通過 login 雲函數獲取 openid。

現在我們來開發第一個基於雲的小程序,這個小程序非常簡單,就是在一個集合中插入一條數據,也就是一個 JSON 格式的文本。
一個集合就相當於一個表。選擇環境后,小程序就會默認有一個數據庫,所以就不需要單獨創建數據庫了,只需要在該數據庫中創建若干個集合(表)即可。
首先打開雲開發控制台,切換到“數據庫”頁面,單后單擊左上角的“添加集合”,彈出如下圖所示的“添加集合”對話框,輸入集合的名字,然后單擊“確定”按鈕添加集合。

創建一個新集合后的效果如下圖所示。可以通過單擊右側的“添加記錄”導入 json 或 csv 文件,每個文件最大 50 MB。不過本課並不會通過雲開發控制台導入,而是使用代碼來插入文檔。

獲得 openid 后,會跳到 userConsole 頁面,因此我們在這個頁面的 onLoad() 函數中向 test 集合插入一個 json 文檔。
在小程序開發工具中定位到 userConsole.js 文件,並找到 onLoad() 函數,如下圖所示。

在 onLoad() 函數中會從全局變量(globalData)中獲取 openid。操作集合首先要通過 init() 函數初始化環境,init() 函數的語法格式如下:
wx.cloud.init({env:envname})
其中,envname 是字符串類型的值,表示要使用的環境名,因為在前面已經創建了一個名為 minicloud 的環境了,所以本例的 envname 的值是'minicloud'。
使用下面的代碼獲取數據庫和集合對象:
const db = wx.cloud.database() const test = db.collection('test')
其中,test 是前面建立的集合名。
最后使用 add() 方法插入 json 格式的數據,完整的代碼如下:
wx.cloud.init({env:'minicloud'}) const db = wx.cloud.database() const test = db.collection('test') test.add({ // data 字段表示需新增的 JSON 數據 data: { name: "Bill", age:30 }, success: function (res) { // 輸出成功插入后的id以及其他信息 console.log(res) } })
現在重新運行程序,獲取 openid 后,就會在小程序開發者工具的 Console 中看到如下圖的信息。

回到雲開發控制台,會看到 test 集合多了如下圖所示的數據,這表明 json 文檔已經插入成功。

現在來完善前面編寫的基於雲的小程序,這個小程序盡管可以向雲數據庫中插入數據,不過代碼與模板代碼混在了一起,在真正的小程序項目中,不可能讓用戶先單擊按鈕獲得 openid,再進行下面的操作,因此現在需要重新編寫基於雲的小程序,主要包括如下功能。
- 從文本輸入組件中輸入姓名和年齡,單擊“插入數據”按鈕向雲數據庫插入包含姓名和年齡的數據。
- 從文本輸入組件中輸入記錄 ID,單擊“查詢數據”按鈕,從雲數據庫中查詢相關的數據,並將查詢到的數據中的姓名和年齡顯示在頁面上。
小程序的主界面如下圖所示。

為了在我們自己頁面上實現這些功能,首先在小程序工程中創建一個 main 目錄,並創建如下圖所示的文件。

接下來修改 app.json 文件,將 main 頁面變成首頁(第一個顯示的頁面),也就是將“pages/main/main”放在 pages 數組的第一個元素的位置,修改后的 app.json 文件的內容如下:
{
"cloud": true, "pages": [ "pages/main/main", "pages/userConsole/userConsole", "pages/storageConsole/storageConsole", "pages/databaseGuide/databaseGuide", "pages/addFunction/addFunction", "pages/deployFunctions/deployFunctions", "pages/chooseLib/chooseLib" ], "window": { "backgroundColor": "#F6F6F6", "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#F6F6F6", "navigationBarTitleText": "雲開發 QuickStart", "navigationBarTextStyle": "black" } }
現在重新運行小程序,會看到 main 頁面已經成為了小程序的首頁。由於本例的頁面需要用到一些組件,因而需要先在 main.wxml 文件中輸入下面的代碼完成 main 頁面的布局。
<view> <input style='margin-top: 40rpx;' placeholder="請輸入姓名" value="{{name}}" bindinput="bindKeyInputName" /> <input style='margin-top: 40rpx;' placeholder="請輸入年齡" value="{{age}}" bindinput="bindKeyInputAge" /> <button style='margin-top: 40rpx;' bindtap='insertData'>插入數據</button> <input style='margin-top: 40rpx;' placeholder="請輸入記錄ID" value="{{recordId}}" bindinput="bindKeyInputId" /> <button style='margin-top: 40rpx;' bindtap='queryData'>查詢數據</button> <text style='margin-top: 40rpx;'> 姓名:{{nameResult}} </text> <text style='margin-top: 80rpx;'> 年齡:{{ageResult}} </text> </view>
在 main.wxml 文件中,包含 3 個 <input>組件和 2 個 text 組件,這 5 個組件分別與 age、name、recordId,nameResult 和 ageResult 五個變量綁定,修改和獲取這 5 個組件的值也只需要考慮這 5 個變量即可。
在小程序中調用雲 API 之前,必須要獲取小程序的 openid,這個 openid 表示當前小程序的用戶 ID。由於進入小程序必須要通過微信,因而小程序使用與微信相同的用戶驗證體系,因此,小程序就不需要單獨登錄了,而 openid 就是小程序是否登錄的憑證。
獲取 openid 的代碼已經包含在模板中了,只需要找到 index.js 文件,並搜索 onGetOpenid() 函數,會看到如下的代碼。
onGetOpenid: function() { // 調用雲函數 wx.cloud.callFunction({ name: 'login', data: {}, success: res => { console.log('[雲函數] [login] user openid: ', res.result.openid) app.globalData.openid = res.result.openid wx.navigateTo({ url: '../userConsole/userConsole', }) }, fail: err => { console.error('[雲函數] [login] 調用失敗', err) wx.navigateTo({ url: '../deployFunctions/deployFunctions', }) } }) }
上面的代碼用於調用名為 login 的雲函數獲取小程序的 openid。通常只需要將 onGetOpenid() 函數中的代碼直接復制到 main.js 文件中的 onLoad() 函數即可。
向雲數據庫插入數據的代碼前面已經學過,一會兒大家可以看本例完整的代碼。從雲數據庫中查詢數據可以使用下面的代碼。
db.collection(集合名).doc(記錄ID).get(
{
// 查詢到數據后觸發,res參數值包含的查詢到 數據 success:function(res) { }, // 未查詢到數據觸發 fail:function(res) { } })
main.js 中完整的實現代碼如下:
// miniprogram/pages/main/main.js const app = getApp() Page({ /** * 頁面的初始數據 */ db:undefined, test:undefined, data: { name:'', age:'', recordId:'', nameResult:'', ageResult:'' }, /** * 生命周期函數--監聽頁面加載 */ onLoad: function (options) { var that = this // 調用login雲函數獲取openid wx.cloud.callFunction({ name: 'login', data: {}, success: res => { console.log('[雲函數] [login] user openid: ', res.result.openid) app.globalData.openid = res.result.openid wx.cloud.init({ env: 'minicloud' }) that.db = wx.cloud.database() that.test = that.db.collection('test') }, fail: err => { console.error('[雲函數] [login] 調用失敗', err) wx.navigateTo({ url: '../deployFunctions/deployFunctions', }) } }) }, // 單擊“插入數據”按鈕調用該函數 insertData:function() { var that = this try { // 將年齡轉換為整數類型值 var age = parseInt(that.data.age) // 如果輸入的年齡不是數字,會顯示錯誤對話框,並退出該函數 if(isNaN(age)) { // 顯示錯誤對話框 wx.showModal({ title: '錯誤', content: '請輸入正確的年齡', showCancel: false }) return } // 向test數據集添加記錄 this.test.add({ // data 字段表示需新增的 JSON 數據 data: { name: that.data.name, age: age }, // 數據插入成功,調用該函數 success: function (res) { console.log(res) wx.showModal({ title: '成功', content: '成功插入記錄', showCancel:false }) that.setData({ name:'', age:'' }) } }) } catch(e) { wx.showModal({ title: '錯誤', content: e.message, showCancel: false }) } }, // 單擊“查詢數據”按鈕執行該函數 queryData:function() { var that = this // 根據記錄ID搜索數據集 this.db.collection('test').doc(this.data.recordId).get({ // 找到記錄集調用 success: function (res) { // 將查詢結果顯示在頁面上 that.setData({ nameResult:res.data.name, ageResult:res.data.age }) }, // 未查到數據時調用 fail:function(res) { wx.showModal({ title: '錯誤', content: '沒有找到記錄', showCancel: false }) } }) }, // 下面的函數用於當更新input組件中的值時同時更新對應變量的值 bindKeyInputName: function (e) { this.setData({ name: e.detail.value }) }, bindKeyInputAge:function(e) { this.setData({ age: e.detail.value }) }, bindKeyInputId:function(e) { this.setData({ recordId:e.detail.value }) }, })
現在重新運行小程序,並添加一些數據,看到雲開發控制台中的 test 集合下多了幾條記錄,如下圖所示,這表明已經將數據成功插入 test 集合。

現在回到小程序開發界面,在“查詢按鈕”上方的文本輸入框中輸入一條記錄的 ID,單擊“查詢數據”按鈕,會看到按鈕下方會顯示如下圖的查詢結果,如果未查詢到結果,會顯示一個提示對話框。

成功通過 login 雲函數獲取 openid 后,會顯示如下圖的頁面。現在就可以使用雲 API 來開發小程序了。

關注“極客起源”公眾號,下載本文源代碼,公眾號二維碼如下:
