筆者最近涉獵了小程式相關的知識,于是利用周末時間開發了一款類似于同僚的小程式,深度體驗了小程式雲開發模式提供的雲函數、資料庫、存儲三大能力。關于雲開發,可參考文檔:小程式·雲開發。
個人感覺雲開發帶來的最大好處是鑒權流程的簡化和對後端的弱化,是以像筆者這種從未接觸過小程式開發的人也能夠在周末兩天時間内開發出一個功能完備、體驗閉環的勉強能用的産品。
最後,本文并不是搬運官方文檔,也不會詳細介紹開發工具和雲開發背景的使用,是以建議結合上面給出文檔連結一起消化本文。
<!--more-->
功能分析
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pml2ZucjYqVGa5RXbjN2LcZDN4IDOxIzLcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.gif)
該小程式功能目前較為簡單(釋出文章、浏覽文章、釋出評論),可用下圖表示,無需贅述:
由架構圖可知,雲開發的資料庫(存文章、存評論)、存儲(圖檔)、雲函數(讀、寫、更新資料庫等)都将涉及,很好地達到了練手的目的。
釋出文章
如果文章不帶圖檔,直接寫資料庫即可,如果帶圖檔則需要先存入圖檔到雲開發提供的存儲中,拿到傳回的fileId(可了解為圖檔的url)再一并寫入資料庫,核心代碼:
for (let i = 0; i < img_url.length; i++) {
var str = img_url[i];
var obj = str.lastIndexOf("/");
var fileName = str.substr(obj + 1)
console.log(fileName)
wx.cloud.uploadFile({
cloudPath: 'post_images/' + fileName,//必須指定檔案名,否則傳回的檔案id不對
filePath: img_url[i], // 小程式臨時檔案路徑
success: res => {
// get resource ID:
console.log(res)
//把上傳成功的圖檔的位址放入數組中
img_url_ok.push(res.fileID)
//如果全部傳完,則可以将圖檔路徑儲存到資料庫
if (img_url_ok.length == img_url.length) {
console.log(img_url_ok)
that.publish(img_url_ok)
}
},
fail: err => {
// handle error
console.log('fail: ' + err.errMsg)
}
})
}
複制
通過
img_url_ok.length == img_url.length
我們确定所有圖檔已經上傳完成并傳回了對應的id,然後執行寫入資料庫的操作:
/**
* 執行釋出時圖檔已經上傳完成,寫入資料庫的是圖檔的fileId
*/
publish: function(img_url_ok) {
wx.cloud.init()
wx.cloud.callFunction({
name: 'publish_post',
data: {
openid: app.globalData.openId,// 這個雲端其實能直接拿到
author_name: app.globalData.userInfo.nickName,
content: this.data.content,
image_url: img_url_ok,
publish_time: "",
update_time: ""//目前讓伺服器自己生成這兩個時間
},
success: function (res) {
// 強制重新整理,這個傳參很粗暴
var pages = getCurrentPages(); // 擷取頁面棧
var prevPage = pages[pages.length - 2]; // 上一個頁面
prevPage.setData({
update: true
})
wx.hideLoading()
wx.navigateBack({
delta: 1
})
},
fail: console.error
})
},
複制
通過
wx.cloud.callFunction
我們調用了一個雲函數(通過
name
指定函數名),并将文章内容
content
和圖檔
image_url
以及其他資訊(釋出者昵稱、id等)一并傳到雲端。然後再看看這個雲函數:
exports.main = async (event, context) => {
try {
return await db.collection('post_collection').add({
// data 字段表示需新增的 JSON 資料
data: {
// 釋出時小程式傳入
//author_id: event.openid,不要自己傳,用sdk自帶的
author_id: event.userInfo.openId,
author_name: event.author_name,
content: event.content,
image_url: event.image_url,
// 伺服器時間和本地時間會造成什麼影響,需要評估
publish_time: new Date(),
// update_time: event.update_time,// 最近一次更新時間,釋出或者評論觸發更新,目前用伺服器端時間
update_time: new Date(),
// 預設值,一些目前還沒開發,是以沒設定
// comment_count: 0,//評論數,直接讀資料庫,避免兩個資料表示同一含義
watch_count: 3,//浏覽數
// star_count: 0,//TODO:收藏人數
}
})
} catch (e) {
console.error(e)
}
}
複制
可以看到,雲函數寫入了一條資料庫記錄,我們的參數通過
event
這個變量帶了進來。
擷取文章清單
所謂擷取文章清單其實就是讀上一節寫入的資料庫,但是我們并不需要全部資訊(例如圖檔url),并且要求按照時間排序,如果熟悉資料庫的話,會發現這又是一條查詢語句罷了:
exports.main = async (event, context) => {
return {
postlist: await db.collection('post_collection').field({// 指定需要傳回的字段
_id: true,
author_name: true,
content: true,
title: true,
watch_count: true
}).orderBy('update_time', 'desc').get(),//指定排序依據
}
}
複制
浏覽文章内容
浏覽文章内容及給定一個文章的id,由文章清單點選時帶入:
onItemClick: function (e) {
console.log(e.currentTarget.dataset.postid)
wx.navigateTo({
url: '../postdetail/postdetail?postid=' + e.currentTarget.dataset.postid,
})
},
複制
然後在雲函數中根據這個id拿到全部資料:
exports.main = async (event, context) => {
return {
postdetail: await db.collection('post_collection').where({
_id: event.postid
}).get(),
}
}
複制
拿到全部資料後,再根據圖檔id去加載貼子的圖檔:
// 擷取内容
wx.cloud.callFunction({
// 雲函數名稱
name: 'get_post_detail',
data: {
postid: options.postid
},
success: function (res) {
var postdetail = res.result.postdetail.data[0];
that.setData({
detail: postdetail,
contentLoaded: true
})
that.downloadImages(postdetail.image_url)
},
fail: console.error
})
複制
這裡
that.downloadImages(postdetail.image_url)
即加載圖檔:
/**
* 從資料庫擷取圖檔的fileId,然後去雲存儲下載下傳,最後加載出來
*/
downloadImages: function(image_urls){
var that = this
if(image_urls.length == 0){
return
} else {
var urls = []
for(let i = 0; i < image_urls.length; i++) {
wx.cloud.downloadFile({
fileID: image_urls[i],
success: res => {
// get temp file path
console.log(res.tempFilePath)
urls.push(res.tempFilePath)
if (urls.length == image_urls.length) {
console.log(urls)
that.setData({
imageUrls: urls,
imagesLoaded: true
})
}
},
fail: err => {
// handle error
}
})
}
}
},
複制
發表評論
發表評論和釋出文章邏輯類似,隻是寫入的資料不同,不做贅述。
總結
前面說過,雲開發弱化了後端(簡化鑒權本質也是弱化後端),這樣帶來的好處就是提高了開發效率,因為前後端聯調向來都是一件耗時間的事情,而且小程式本身主打的就是小型應用,實在沒有必要引入過多的開發人員。但雲開發也不是萬能的,例如我一開始想做RSS閱讀器,那麼後端就需要聚合資訊,目前雲開發還做不了。個人感覺隻要是資訊類的小程式,如新聞類、視訊類,雲開發目前都很乏力,因為資料庫的支援還過于簡陋(也可能是我太菜,沒發現很好的解決辦法,歡迎拍磚)。但如果是本文提及的這種使用者自己也會産生資訊的小程式,那麼雲開發則會有開發效率上的優勢。最後就是雲開發目前提供的2G資料庫和5G存儲,對于一些使用者量較多的小程式是否足夠也是個問題,目前也沒見有付費版。
總的類說,初次接觸小程式開發,還是發現有不少值得借鑒學習之處。
源碼:vimerzhao/RssHub