寫在前面
開發小程式,但是:沒有後端!沒有運維!沒有 DBA!沒有域名!沒有證照!沒有錢!沒有時間!沒有精力!
沒有關係,會 javascript 就可以,小程式•雲開發帶你起飛!
開發者可以使用雲開發開發微信小程式、小遊戲,無需搭建伺服器,即可使用雲端能力。雲開發為開發者提供完整的雲端支援,弱化後端和運維概念,無需搭建伺服器,使用平臺提供的 API 進行核心業務開發,即可實現快速上線和迭代,同時這一能力,同開發者已經使用的雲服務相互相容,並不互斥。
目前提供三大基礎能力支援:
- 雲函式:在雲端執行的程式碼,微信私有協議天然鑑權,開發者只需編寫自身業務邏輯程式碼
- 資料庫:一個既可在小程式前端操作,也能在雲函式中讀寫的 JSON 資料庫
- 儲存:在小程式前端直接上傳/下載雲端檔案,在雲開發控制檯視覺化管理
一步一步搭建
本文將一步一步教你使用 小程式•雲開發 + Omip + Comi 搭建一個支援 markdown 和程式碼高亮的小程式內容展示和釋出系統。
預覽:
1.建表
操作路徑: 微信開發者工具→雲開發→資料庫→新增集合
article 集合欄位說明:
欄位 | 說明 |
---|---|
_id | 資料的唯一 id,使用者寫入時系統自動生產 |
_openid | 使用者的唯一標識,使用者寫入時系統自動生產 |
createTime | 文章建立時間 |
md | 文章內容 |
order | 文章的順序 |
title | 文章的標題 |
很明顯,這個表用來儲存所有的文章。然後設定表的讀寫許可權:
因為後續可能支援使用者發表文章,所有設定成第一個。
2.初始化專案目錄
$ npm i omi-cli -g
$ omi init-cloud my-app
$ cd my-app
$ npm start
複製程式碼
這裡是使用 omip 作為腳手架,也支援 Omi mps-cloud 建立原生小程式的雲開發的腳手架:
$ npm i omi-cli -g
$ omi init-mps-cloud my-app
$ cd my-app/miniprogram
$ npm install
$ npm start
複製程式碼
3.專案初始化 app.js
import './app.css'
import './pages/list/index'
import { render, WeElement, define } from 'omi'
define('my-app', class extends WeElement {
config = {
pages: [
'pages/list/index',
'pages/detail/index',
'pages/import/index'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'Omi Cloud',
navigationBarTextStyle: 'black'
}
}
install() {
if (!wx.cloud) {
console.error('請使用 2.2.3 或以上的基礎庫以使用雲能力')
} else {
wx.cloud.init({
traceUser: true,
})
this.globalData.db = wx.cloud.database({
env: 'test-06eb2e'
})
}
}
render() {
return (
<page-list />
)
}
})
render(<my-app />, '#app')
複製程式碼
wx.cloud.database
程式碼引數裡的 env 可以從上面獲取到,一般建立兩個環境,一個使用者測試環境,一個用於生產環境。
- pages/list/index 文章列表首頁
- pages/detail/index 文章詳情夜
- pages/import/index 文章匯入頁(先簡單通過程式碼匯入 markdown,沒提供 UI)
匯入 markdown 資料
import { WeElement, define } from 'omi'
import data from './test.md'
const app = getApp()
define('page-import', class extends WeElement {
installed() {
wx.cloud.callFunction({
name: 'login',
data: {},
success: res => {
app.globalData.openid = res.result.openid
app.globalData.db.collection('article').add({
data: {
md: data.md,
title: 'test',
createTime: app.globalData.db.serverDate()
},
success: (res) => {
console.log(res)
},
fail: err => {
console.error('[雲函式] [login] 呼叫失敗', err)
}
})
},
fail: err => {
console.error('[雲函式] [login] 呼叫失敗', err)
}
})
}
...
...
})
複製程式碼
注意三點:
- 通過
wx.cloud.callFunction
呼叫雲函式進行登陸,且獲取 openid,接著匯入資料會自動帶上提交該 openid。 - 通過
app.globalData.db.serverDate()
獲取服務端時間,客戶端時間不可靠 - 文章匯入只由管理員負責
注意 import data from './test.md'
,這裡通過修改 omip 裡的 scripts 邏輯實現。
這裡解釋下 import markdown 原理:
let code = fs.readFileSync(item).toString()
if (path.extname(item) === '.md') {
code = `export default { md: \`${code.replace(/`/g, '\\`').replace(/\$/g, '\\$')}\` }`
}
複製程式碼
檢測到 md 字尾的檔案,把檔案裡的 markdown 字串對關鍵字進行轉義然後變成一個 js 模組。
這也算是使用中間編譯的好處之一吧,如果原生的小程式目前沒辦法 import markdown 檔案,當然原生小程式 API 和周邊生態在不斷進化,騰訊 Omi 團隊開發的 mps 框架 就是讓你在原生小程式中使用 jsx 和 less。
上面的詳細程式碼可以點選這裡檢視到。
列表頁
請求 list 資料
//先展示 loading
wx.showLoading({
title: '載入中'
})
//呼叫雲函式獲取 openid
wx.cloud.callFunction({
name: 'login',
data: {},
success: res => {
app.globalData.openid = res.result.openid
app.globalData.db.collection('article').field({
title: true,
_id: true,
order: true
}).get().then(res => {
this.data.list = res.data.sort(function (a, b) {
return a.order - b.order
})
this.update()
wx.hideLoading()
})
},
fail: err => {
console.error('[雲函式] [login] 呼叫失敗', err)
}
})
複製程式碼
- 請求 list,通過 field 方法篩選欄位,畢竟 list 不需要 md 欄位,這樣可以減少資料傳輸,節約頻寬
- 通過 order 欄位對 list 進行排序(這樣管理員不需要發版本就可以手動調整 order 給 list 排序)
完整的程式碼:
import { WeElement, define } from 'omi'
import './index.css'
import arrowPng from './arrow.png'
//獲取應用例項
const app = getApp()
define('page-about', class extends WeElement {
config = {
navigationBarBackgroundColor: '#24292e',
navigationBarTextStyle: 'white',
navigationBarTitleText: 'Omi',
backgroundColor: '#ccc',
backgroundTextStyle: 'light'
}
data = {
list: []
}
installed() {
wx.showLoading({
title: '載入中'
})
wx.cloud.callFunction({
name: 'login',
data: {},
success: res => {
console.log('[雲函式] [login] user openid: ', res.result.openid)
app.globalData.openid = res.result.openid
app.globalData.db.collection('article').field({
title: true,
_id: true,
order: true
}).get().then(res => {
this.data.list = res.data.sort(function (a, b) {
return a.order - b.order
})
this.update()
wx.hideLoading()
})
},
fail: err => {
console.error('[雲函式] [login] 呼叫失敗', err)
}
})
}
gotoDetail = (evt) => {
wx.navigateTo({
url: '../detail/index?id=' + evt.currentTarget.dataset.id
})
}
render() {
return (
<view class='ctn'>
{list.map(item => (
<view class='item' data-id={item._id} bindtap={this.gotoDetail}>
<text>{item.title}</text>
<image src={arrowPng}></image>
</view>
))}
</view>
)
}
})
複製程式碼
Omip 可以直接讓你使用 jsx 書寫 wxml 結構。編譯出的 wxml 如下:
<block>
<view class="ctn">
<view class="item" data-id="{{item._id}}" bindtap="gotoDetail" wx:for="{{list}}" wx:for-item="item"><text>{{item.title}}</text>
<image src="{{arrowPng}}"></image>
</view>
</view>
</block>
複製程式碼
這裡需要注意,點選每一項跳轉詳情也一定要使用 evt.currentTarget.dataset.id
,而不能使用 evt.target.dataset.id
。這樣點選到文字或者image
上獲取不到 id。
文章詳情展示
這裡使用 Comi 進行 markdown 渲染! Comi 讀 ['kəʊmɪ],類似中文 科米,是騰訊 Omi 團隊開發的小程式程式碼高亮和 markdown 渲染元件。Comi 是基於下面幾個優秀的社群元件進行二次開發而成。
- wxParse
- remarkable
- html2json
- htmlparser
- prism
效果預覽:
import { WeElement, define } from 'omi'
import './index.css'
import comi from '../../components/comi/comi'
//獲取應用例項
const app = getApp()
define('page-about', class extends WeElement {
config = {
navigationBarBackgroundColor: '#24292e',
navigationBarTextStyle: 'white',
navigationBarTitleText: ' ',
backgroundColor: '#eeeeee',
backgroundTextStyle: 'light'
}
install(options) {
wx.showLoading({
title: '載入中'
})
app.globalData.db.collection('article').doc(options.id).get().then(res=>{
comi(res.data.md, this.$scope)
wx.hideLoading()
}).catch(err => {
console.error(err)
})
}
render() {
return (
<view>
<include src="../../components/comi/comi.wxml" />
</view>
)
}
})
複製程式碼
除了在 omip 中使用,原生小程式也可以使用 Comi:
先拷貝 此目錄 到你的專案。
js:
const comi = require('../../comi/comi.js');
Page({
onLoad: function () {
comi(`你要渲染的 md!`, this)
}
})
複製程式碼
wxml:
<include src="../../comi/comi.wxml" />
複製程式碼
wxss:
@import "../../comi/comi.wxss";
複製程式碼
大功告成,簡單把!
雲函式與除錯
雲函式即在雲端(伺服器端)執行的函式。在物理設計上,一個雲函式可由多個檔案組成,佔用一定量的 CPU 記憶體等計算資源;各雲函式完全獨立;可分別部署在不同的地區。開發者無需購買、搭建伺服器,只需編寫函式程式碼並部署到雲端即可在小程式端呼叫,同時雲函式之間也可互相呼叫。
一個雲函式的寫法與一個在本地定義的 JavaScript 方法無異,程式碼執行在雲端 Node.js 中。當雲函式被小程式端呼叫時,定義的程式碼會被放在 Node.js 執行環境中執行。我們可以如在 Node.js 環境中使用 JavaScript 一樣在雲函式中進行網路請求等操作,而且我們還可以通過雲函式後端 SDK 搭配使用多種服務,比如使用雲函式 SDK 中提供的資料庫和儲存 API 進行資料庫和儲存的操作,這部分可參考資料庫和儲存後端 API 文件。
雲開發的雲函式的獨特優勢在於與微信登入鑑權的無縫整合。當小程式端呼叫雲函式時,雲函式的傳入引數中會被注入小程式端使用者的 openid,開發者無需校驗 openid 的正確性因為微信已經完成了這部分鑑權,開發者可以直接使用該 openid。
在本文的小程式裡有個 todo 的案例,裡面的 remove 使用了雲函式,用於清空所有已完成的任務。
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
const _ = db.command
exports.main = async (event, context) => {
try {
return await db.collection('todo').where({
done: true
}).remove()
} catch (e) {
console.error(e)
}
}
複製程式碼
不過最新的IED,雲函式支援了本地除錯功能,感興趣的可以點選這裡瞭解下。