最近在刷小紅書時,看到不少人在分享自己的微信小程序如何靠廣告月入上萬,甚至更多。
這種説法不能説不真實,只能説肯定不是這麼簡單的事情。畢竟廣告收入的多少,歸根結底還是取決於用户量,不可能隨便做個小程序,就能吸引大量用户來看廣告。
不過,完全説不可能也不太準確,畢竟人活着總得有夢想。而且其實做一個簡單的小程序成本並不高,尤其得益於雲開發。小程序後期沒有域名、服務器等額外的軟成本,所有內容都可以部署在微信平台上。如果小程序沒有火,每個月基本上只需要支付20元的基礎費用,這幾乎就是唯一的支出。所以,如果廣告收入能超過20元,那就算是賺到了。
正好最近有點空閒時間,我也挺好奇微信小程序的開發流程相比之前有什麼變化,索性就研究了一下,並把整個過程記錄下來,方便以後參考。於是,就有了這篇文章。
開發前準備
註冊微信公眾平台
首先前往 微信公眾平台 並掃碼登錄。如果是新用户,掃碼時會引導你進行網頁註冊。
註冊所需的資料並不複雜,但需要注意微信對不同註冊主體的限制。個人主體可以註冊小程序,但無法使用支付等涉及資金交易的功能。這也是為什麼小紅書上的宣傳總是強調廣告收入。畢竟,除非真有富哥富姐玩真心話大冒險輸了私下給你轉賬,否則廣告收入幾乎是個人主體小程序唯一的盈利方式。
註冊鏈接:https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index...
鏈接:https://mp.weixin.qq.com
創建微信小程序
一個微信公眾平台賬號,簡單來説就是一個 開發者賬號,它對應着一個 AppID(小程序ID) 。
微信官方提供了 微信開發者工具,用於小程序的開發。
因此,小程序的開發過程可以概括為:
- 註冊賬號
- 獲取AppID
- 下載並安裝微信開發者工具
- 在微信開發者工具中創建項目,綁定AppID後開始開發
微信開發者工具下載地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/sta...
可選:小程序備案
已經確定小程序內容(名稱 / logo)的情況下,可以提前進行小程序備案
詳見:小程序備案
開始開發
小程序的開發方式與 Vue 類似,但整體上經過了微信的“魔改”。通過類似 HTML 的 WXML 構建頁面,類似 CSS 的 WXSS 描述樣式,以及通過類似 JavaScript 的 WXJS 渲染頁面。
需要注意的是,雖然 WXSS 與 CSS 基本相似,但許多 CSS3 特性並未被繼承到 WXSS 中。此外,小程序的渲染方式與傳統網頁有所不同,因此在開發時需要特別關注頁面樣式在不同設備上的兼容性和展示效果。
整體説明
小程序創建後,會得到這樣一個基礎目錄
your-app/
│
├── assets/ # 存放靜態資源文件(如圖片、字體等)
│ ├── logo.png
│ └── bg.jpg
│
├── components/ # 自定義組件
│ ├── header/ # 頭部組件文件夾
│ │ ├── header.wxml # 組件的結構文件
│ │ ├── header.wxss # 組件的樣式文件
│ │ ├── header.js # 組件的邏輯文件
│ │ └── header.json # 組件的配置文件
│ │
│ └── footer/ # 底部組件文件夾
│ ├── footer.wxml
│ ├── footer.wxss
│ ├── footer.js
│ └── footer.json
│
├── pages/ # 存放小程序頁面
│ ├── index/ # 首頁頁面文件夾
│ │ ├── index.wxml # 頁面結構文件(HTML-like)
│ │ ├── index.wxss # 頁面樣式文件(CSS-like)
│ │ ├── index.js # 頁面邏輯文件(JS)
│ │ └── index.json # 頁面配置文件
│ │
│ └── other/ # 其他頁面
│ ├── other.wxml
│ ├── other.wxss
│ ├── other.js
│ └── other.json
│
├── utils/ # 存放工具函數等公共代碼
│ ├── util.js
│ └── helper.js
│
├── app.js # 小程序的入口文件
├── app.json # 小程序全局配置文件
├── app.wxss # 小程序全局樣式文件
└── project.config.json# 小程序項目配置文件(IDE用)
頁面説明
小程序的每個頁面或組件通常由同名的 wxml、wxss、js 和 json 四個文件構成,這些文件之間會自動關聯,無需額外的引用配置。
wxml (微信標記語言,類似HTML)
- 負責頁面的結構和佈局,定義頁面中的元素。
- 通過 WXML 來編寫頁面的視圖結構。
<!-- wxml 文件 -->
<view class="container">
<text>{{title}}</text>
</view>
wxss(微信樣式表,類似CSS)
- 負責頁面的樣式設置,定義頁面中元素的外觀、佈局等。
-
wxss 是 CSS 的一種擴展,支持大部分標準的 CSS 特性,同時增加了小程序特有的一些功能,如尺寸單位rpx(響應式像素)。
/* wxss 文件 */
.container {
width: 100%;
padding: 20px;
background-color: #f0f0f0;
}
js(JavaScript)
- 用於頁面的邏輯處理,包括數據的處理、事件的綁定、頁面生命週期的管理等。
- 通過
Page() 或Component() 定義頁面的行為和生命週期方法(如onLoad、onShow 等)。
// js 文件
Page({
data: {
title: 'Hello, 小程序!'
},
onLoad: function() {
console.log('頁面加載');
}
});
json(配置文件)
- 用於頁面的配置,比如頁面的導航欄、標題、窗口背景色等。
- 頁面和組件的配置也通過
json 文件來指定,包括頁面是否啓用分享、是否使用微信的下拉刷新等。
{
"navigationBarTitleText": "首頁",
"enablePullDownRefresh": true
}
組件
組件與頁面類似,由同名的 wxml、wxss、js 和 json 四個文件組成。
可以簡單理解為,組件就是一個“可複用的小頁面”或“功能模塊”。
組件的意義在於封裝可複用的 UI 結構和邏輯。例如,在小程序中,每個頁面可能都會包含一個相同的標題欄,如果不使用組件,就需要在每個頁面單獨編寫一遍,而使用組件後,只需封裝一個標題欄組件,並在各個頁面中引用即可。這樣不僅減少了冗餘代碼,提高了開發效率,還能在需要調整時,只修改組件代碼就能同步更新所有頁面,避免遺漏或重複修改。
組件的引用
在對應頁面的 json 配置文件(如 index.json)中,使用 usingComponents 引入組件。例如,假設組件位於 components/my-component/my-component 目錄下:
{
"usingComponents": {
"my-component": "/components/my-component/my-component"
}
}
在頁面的 wxml 文件中,像 HTML 標籤一樣使用組件:
<my-component></my-component>
生命週期
小程序根據 js 中的 Page() 或 Component() 來區分頁面或組件,他們會有各自不同的生命週期
小程序的開發多數都圍繞着頁面的生命週期進行
頁面
頁面中的自定義方法如下圖表格所示:
頁面進行到對應節點時便會觸發對應的生命週期函數,可以不進行聲明,如果不進行聲明則不會被觸發
| 生命週期函數 | 觸發時機 | 適用場景 |
|---|---|---|
| onLoad(options) | 頁面 加載 時觸發(僅觸發一次) | 獲取頁面跳轉參數、初始化數據 |
| onReady() | 頁面 首次渲染完成 時觸發(僅觸發一次) | 獲取 DOM 節點信息 |
| onShow() | 頁面 每次顯示 時觸發 | 頁面進入前台,適合刷新數據 |
| onHide() | 頁面 隱藏 時觸發 | 頁面跳轉到其他頁面 |
| onUnload() | 頁面 卸載 時觸發 | 適用於釋放資源、清除定時器 |
| onPullDownRefresh() | 用户 下拉刷新 時觸發 | 刷新頁面數據(需要在 json 裏開啓) |
| onReachBottom() | 用户 滾動到底部 時觸發 | 適用於分頁加載數據 |
| onShareAppMessage() | 用户點擊 分享按鈕 時觸發 | 自定義分享內容 |
| onShareTimeline() | 用户點擊 分享到朋友圈 時觸發 | 適用於朋友圈分享 |
| onPageScroll(event) | 頁面 滾動時 觸發 | 監聽滾動位置 |
| onResize(event) | 頁面 尺寸變化 時觸發 | 適用於屏幕旋轉等情況 |
注意:小程序的頁面管理方式和瀏覽器的 單頁應用(SPA) 類似,採用的是 堆棧管理機制,即:
- 頁面不會被立即銷燬,而是存儲在頁面棧中。
- 新頁面入棧,舊頁面仍然保留在內存中,不會觸發
onLoad。 - 返回舊頁面時,舊頁面不會重新加載,但會觸發
onShow。
| 操作 | onLoad | onShow | onHide | onUnload |
|---|---|---|---|---|
| 進入頁面 A | ✅ 觸發 | ✅ 觸發 | ❌ | ❌ |
| 從 A 跳轉到 B | ❌ | ❌ | ✅ 觸發 | ❌ |
| 返回 A(B -> A) | ❌ | ✅ 觸發 | ❌ | ❌ |
| A -> B -> 關閉 B | ❌ | ✅ 觸發 | ❌ | ✅(B 卸載) |
示例
Page({
/**
* 頁面的初始數據
*
* 頁面的初始數據是一個對象,可以包含各種屬性,這些屬性將用於頁面渲染
* 頁面的數據會在頁面加載時自動傳入頁面的 wxml
* 通過 data 設置的數據,可以在 wxml 中進行綁定,從而在頁面中渲染
* 例如下面的數據,可以直接在 wxml 中使用 {{message}} 進行展示
* data 中的數據可以在頁面的 js 中通過 this.data 訪問
* 通過 this.setData 方法修改 data 中的數據,將重新渲染頁面
*/
data: {
message: "Hello, 小程序!",
count: 0
},
/**
* 生命週期函數 - 監聽頁面加載
* 只在頁面首次加載時觸發一次
* 可用於獲取頁面參數、初始化數據等
*/
onLoad(options) {
console.log("頁面加載:onLoad", options);
// 可以從 options 獲取頁面跳轉時傳遞的參數
if (options.id) {
console.log("頁面參數 ID:", options.id);
}
},
/**
* 生命週期函數 - 監聽頁面初次渲染完成
* 頁面結構已渲染,但未必可見
* 適合操作 DOM
*/
onReady() {
console.log("頁面渲染完成:onReady");
},
/**
* 生命週期函數 - 監聽頁面顯示
* 每次頁面進入前台時觸發(包括返回該頁面)
*/
onShow() {
console.log("頁面顯示:onShow");
},
/**
* 生命週期函數 - 監聽頁面隱藏
* 進入後台或跳轉到其他頁面時觸發
*/
onHide() {
console.log("頁面隱藏:onHide");
},
/**
* 生命週期函數 - 監聽頁面卸載
* 頁面被關閉/銷燬時觸發(如 `wx.navigateBack()` 返回)
* 適合執行清理操作,如釋放定時器
*/
onUnload() {
console.log("頁面卸載:onUnload");
},
/**
* 監聽用户下拉動作(用於刷新頁面)
* 需要在 `page.json` 裏開啓 `"enablePullDownRefresh": true`
*/
onPullDownRefresh() {
console.log("用户觸發下拉刷新:onPullDownRefresh");
// 模擬數據刷新
setTimeout(() => {
this.setData({ message: "數據已刷新" });
wx.stopPullDownRefresh(); // 停止刷新動畫
}, 1000);
},
/**
* 頁面上拉觸底事件(用於加載更多數據)
* 適用於分頁加載數據
*/
onReachBottom() {
console.log("頁面滾動到底部:onReachBottom");
this.setData({ count: this.data.count + 1 });
},
/**
* 監聽用户點擊右上角分享(可自定義分享內容)
* 僅 `onShareAppMessage` 適用於普通分享
*/
onShareAppMessage() {
console.log("用户點擊分享:onShareAppMessage");
return {
title: "這是一個分享標題",
path: "/pages/index/index?id=123" // 可以攜帶參數
};
},
/**
* 監聽用户點擊右上角分享到朋友圈
* 僅 `onShareTimeline` 適用於分享到朋友圈
*/
onShareTimeline() {
console.log("用户分享到朋友圈:onShareTimeline");
return {
title: "分享到朋友圈的標題"
};
},
/**
* 頁面滾動觸發(可用於監聽滾動位置)
*/
onPageScroll(event) {
console.log("頁面滾動:onPageScroll", event.scrollTop);
},
/**
* 頁面尺寸變化時觸發(通常用於適配屏幕旋轉)
*/
onResize(event) {
console.log("頁面尺寸變化:onResize", event);
}
});
組件
組件的行為與 頁面 類似。 通常來説 組件不會自動卸載,而是 隨頁面一起緩存
組件的生命週期與頁面不同,具體生命週期如下:
組件進行到對應節點時便會觸發對應的生命週期函數,可以不進行聲明,如果不進行聲明則不會被觸發
| 生命週期 | 作用 |
|---|---|
| created() | 組件實例化時觸發,數據未綁定,DOM 結構未生成 |
| attached() | 組件掛載到頁面節點樹時觸發,可獲取 properties |
| ready() | 組件視圖渲染完成,適合操作 DOM |
| moved() | 組件從一個位置移動到另一個位置(較少使用) |
| detached() | 組件被移除,適合清理資源(如定時器、監聽事件) |
| error() | 組件內部發生錯誤時觸發 |
| pageLifetimes.show() | 組件所在的頁面 onShow 時觸發 |
| pageLifetimes.hide() | 組件所在的頁面 onHide 時觸發 |
| pageLifetimes.resize(size) | 組件所在頁面尺寸發生變化時觸發 |
注意:小程序的組件的生命週期比頁面更精細,具體行為取決於組件的使用方式,有以下幾個點需要被注意:
- 組件不會隨頁面
onShow() 觸發,需要手動更新數據。 - 使用
wx:if 可以讓組件重新創建,從而刷新數據。 - 使用
hidden 只是隱藏組件,不會銷燬。
| 行為 | 頁面 onShow() 觸發? | 組件 attached() 觸發? | 組件 detached() 觸發? |
|---|---|---|---|
| wx.navigateTo() | ✅ | ❌ | ❌ |
| wx.navigateBack() | ✅ | ❌ | ❌ |
| wx.switchTab() | ✅ | ❌ | ❌ |
| wx:if 控制組件 | - | ✅(組件被重新創建) | ✅(組件被銷燬) |
| hidden 控制組件 | - | ❌ | ❌ |
示例
Component({
/**
* 組件的屬性列表(外部傳入)
*/
properties: {
title: {
type: String,
value: "默認標題"
},
count: {
type: Number,
value: 0
}
},
/**
* 組件的內部數據
*/
data: {
innerValue: "內部數據"
},
/**
* 組件的方法列表
*/
methods: {
/**
* 自定義方法 - 增加計數
*/
increment() {
this.setData({
count: this.data.count + 1
});
this.triggerEvent("countChanged", { count: this.data.count }); // 觸發事件,通知父組件
},
/**
* 自定義方法 - 組件被點擊
*/
handleTap() {
console.log("組件被點擊");
this.triggerEvent("componentTap", { message: "組件被點擊了" });
}
},
/**
* 組件的生命週期函數
*/
lifetimes: {
/**
* created:組件實例化時觸發(在組件未進入頁面節點樹時)
*/
created() {
console.log("組件實例化:created");
},
/**
* attached:組件掛載到頁面時觸發(類似於頁面的 onLoad)
*/
attached() {
console.log("組件掛載到頁面:attached");
},
/**
* ready:組件視圖渲染完成(類似於頁面的 onReady)
*/
ready() {
console.log("組件視圖渲染完成:ready");
},
/**
* moved:組件被移動到其他節點(很少使用)
*/
moved() {
console.log("組件被移動:moved");
},
/**
* detached:組件從頁面移除時觸發(類似於頁面的 onUnload)
*/
detached() {
console.log("組件被銷燬:detached");
},
/**
* error:組件內部發生錯誤時觸發(如 setData 失敗)
*/
error(err) {
console.error("組件發生錯誤:", err);
}
},
/**
* 舊版生命週期(與 lifetimes 功能類似,可兼容舊版小程序)
*/
pageLifetimes: {
/**
* 組件所在的頁面顯示時觸發(類似於 onShow)
*/
show() {
console.log("組件所在頁面顯示:pageLifetimes.show");
},
/**
* 組件所在的頁面隱藏時觸發(類似於 onHide)
*/
hide() {
console.log("組件所在頁面隱藏:pageLifetimes.hide");
},
/**
* 組件所在的頁面卸載時觸發(類似於 onUnload)
*/
resize(size) {
console.log("組件所在頁面尺寸變化:pageLifetimes.resize", size);
}
}
});
組件的寫法與頁面近乎無二,通常建議將會重複在頁面中出現的部分單獨寫成組件,這樣只要在不同的頁面中引用即可,頁面與組件之間可以相互傳遞數據
事件綁定
在微信小程序中,事件綁定是頁面與用户交互的核心。事件可以綁定到頁面元素上,當用户與元素交互時,觸發相應的 JavaScript 方法,從而實現預期的操作。
小程序提供了多種事件類型,主要如下:
| 事件類型 | 説明 |
|---|---|
| tap | 輕觸事件(點擊) |
| longpress / longtap | 長按(750ms 以上) |
| touchstart | 手指觸摸屏幕 |
| touchmove | 手指在屏幕上滑動 |
| touchend | 手指離開屏幕 |
| touchcancel | 觸摸被打斷,如來電 |
| scroll | 滾動事件 |
| input | 輸入框內容變化 |
| blur | 輸入框失去焦點 |
| focus | 輸入框獲得焦點 |
| change | 選項改變(picker、checkbox、radio 等) |
| confirm | 輸入框回車事件 |
| submit | 表單提交事件 |
| load | 圖片加載完成 |
| error | 組件加載失敗 |
事件的綁定方式
微信小程序中存在多種事件綁定方式,如下:
在 wxml 中,事件綁定是以 綁定方式+事件類型="js中的函數名"
| 方式 | 説明 |
|---|---|
| bind | 事件會冒泡 |
| catch | 事件不會冒泡 |
| capture-bind | 事件在捕獲階段觸發(先父後子) |
| capture-catch | 事件在捕獲階段觸發,且不會冒泡 |
事件的冒泡
微信小程序的事件分為冒泡事件和非冒泡事件
這些事件會從子組件向父組件傳遞:
-
tap(點擊) -
longpress(長按) -
touchstart /touchmove /touchend(觸摸) -
confirm(鍵盤迴車)
冒泡事件可以理解為,當在wxml中,一個視圖容器嵌套另一個視圖容器的情況下,在點擊內部視圖容器時,外部容器的對應事件也會被響應,因為本質上內部組件整個本身就是外部組件內部的一部分
以下文為例:
🔹
bindtap="childTap" → 事件會冒泡,父組件的parentTap() 也會觸發
🔹 catchtap="childTap" → 事件不會冒泡,parentTap() 不會觸發
<view bindtap="parentTap">
<view bindtap="childTap" catchtap="childTap">點擊我</view>
</view>
Page({
parentTap(event) {
console.log("父組件被點擊");
},
childTap(event) {
console.log("子組件被點擊");
}
});
事件對象
所有事件都會帶一個 event 參數:
handleTap(event) {
console.log(event);
// event.currentTarget // 事件綁定的元素
// event.target // 實際觸發事件的元素
// event.detail // 事件的詳細信息(如 `input` 輸入的值)
// event.touches // 當前觸摸點
// event.timeStamp // 事件時間
}
示例:
<view bindtap="handleTap" data-id="123">點擊我</view>
handleTap(event) {
console.log(event.currentTarget.dataset.id); // 輸出 "123"
}
綁定事件的元素可以通過
data- 來賦值,在事件方法中可以通過event.currentTarget.dataset 來獲取即為:如果 WXML 中 填寫的內容為
<view bindtap="handleTap" data-demo="123">點擊我</view> ,那麼在handleTap 方法中就可以通過event.currentTarget.dataset.demo 來獲取值
組件的自定義事件
組件同樣支持自定義事件,其事件類型和綁定方式與頁面一致。不同之處在於,組件的自定義事件需要在 methods 對象中定義相應的方法。
組件的自定義事件中,可以通過 this.triggerEvent 方法向頁面傳遞數據,如下圖所示:
-
子組件:
<button bindtap="sendData">點擊發送</button>Component({ methods: { sendData() { this.triggerEvent('myEvent', { name: '小程序' }); } } }); -
父組件:
<custom-component bind:myEvent="handleEvent"></custom-component>Page({ handleEvent(event) { console.log(event.detail.name); // "小程序" } });
雲開發
説實話,雲開發這個東西很難説有多好。如果是正兒八經的企業項目,還是建議自備服務器,因為自建服務器能提供更大的後端操作空間,很多邏輯都可以交由後端處理,靈活性更高。
雲開發的核心包括 雲函數、雲存儲 和 雲數據庫:
- 雲函數:支持遠程部署 Node.js 代碼,並且可以被微信小程序免鑑權直接調用(類似於內網調用,不需要額外考慮安全驗證)。
- 雲數據庫:提供類 MongoDB 的 NoSQL 數據庫,或支持 MySQL。
- 雲存儲:用於存儲各類文件資源。
從功能上來看,雲開發已經具備了基礎的服務器端能力,但其中也存在一些非常詭異的軟限制。例如,在使用雲數據庫時,每次查詢最多隻能返回 20 條數據,想獲取更多數據必須通過分頁的方式逐步查詢。
不過,整體來看,如果只是一個小微項目,為了一個訪問量不高的小程序特意準備一台服務器,確實有些浪費。而云開發採用按量計費模式,最低 20 元的套餐就能滿足基本需求,相比自建服務器,成本低了不少。所以是否選擇雲開發,還是要看具體需求,見仁見智。
注意: 使用雲開發能力前,需要通過 wx.cloud.init() 進行初始化,一般建議在根目錄 app.js 中的 onLaunch 方法中執行一次即可
雲存儲
上傳
在方法中,直接使用 wx.cloud.uploadFile 方法就可以上傳文件
-
cloudPath:文件存儲在雲端的路徑,可以是任意字符串(建議加文件夾結構)。 -
filePath:本地文件路徑,比如wx.chooseImage() 選擇的圖片路徑。 -
success:上傳成功的回調,res.fileID 是文件的唯一標識,可用於後續訪問。
wx.cloud.uploadFile({
cloudPath: 'example-folder/my-image.png', // 存儲路徑
filePath: tempFilePath, // 本地文件路徑(通過 wx.chooseImage 獲取)
success: res => {
console.log('上傳成功,文件ID:', res.fileID);
},
fail: err => {
console.error('上傳失敗', err);
}
});
訪問或下載
上傳成功後,可以通過 fileID 獲取文件的臨時訪問 URL
wx.cloud.getTempFileURL({
fileList: ['cloud://your-env-id/example-folder/my-image.png'],
success: res => {
console.log('文件可訪問地址:', res.fileList[0].tempFileURL);
},
fail: err => {
console.error('獲取文件 URL 失敗', err);
}
});
刪除文件
如果需要刪除雲存儲中的文件,可以使用 wx.cloud.deleteFile 方法
wx.cloud.deleteFile({
fileList: ['cloud://your-env-id/example-folder/my-image.png'],
success: res => {
console.log('刪除成功', res.fileList);
},
fail: err => {
console.error('刪除失敗', err);
}
});
雲函數
雲函數的核心在於“雲端函數”本身,而非小程序的功能。簡單來説,可以理解為你在微信雲平台上部署了一段 Node.js 代碼,併為該雲函數指定一個名稱。之後,你就可以通過 wx.cloud.callFunction 來調用這個函數了。
大致流程如下:
wx.cloud.callFunction({
name: 'cloud-name', // 雲函數名稱
data: {}, // 傳遞給雲函數的數據
success: res => {
console.log('雲函數返回結果:', res);
},
fail: err => {
console.error('雲函數調用失敗', err);
}
});
有些聰明的朋友可能會開始糾結:小程序已經可以直接使用雲數據庫和雲存儲了,雲函數的意義到底在哪兒呢?
其實,雲函數的作用非常明顯。如果你需要對用户上傳的數據進行清洗、計算、合併等複雜操作,或者需要進行雲端的高級數據處理,這時候雲函數就顯得非常有用。直接在客户端進行這些處理可能會加重小程序的負擔,而使用雲函數可以將這些邏輯封裝到雲端,從而減輕客户端的計算壓力,並提升性能。
另外,如果你是企業主體,可能需要與第三方服務進行集成,比如支付處理、短信發送、郵件服務或社交登錄等。這些外部服務通常需要在後端進行操作,而不適合直接在小程序客户端實現。通過雲函數,你可以安全地與外部API進行交互,並將結果傳遞迴小程序。
最後,如果你有定時任務(例如定期推送消息、清理數據庫、生成報告等),雲函數也可以在雲端定時執行,而不依賴客户端的操作。
雲數據庫
首先你需要獲取數據庫實例,通常是通過 wx.cloud.database() 獲取:
可以在頁面使用數據庫時聲明,也可以在小程序啓動時在 app.js 中註冊為全局變量
查詢數據
查詢數據使用 get() 方法,它返回的是一個 Promise 對象,可以通過 .then() 或 async/await 來獲取數據。
const db = wx.cloud.database()
db.collection('users').get({
success: res => {
console.log('查詢結果', res.data); // 返回查詢的所有數據
},
fail: err => {
console.error('查詢失敗', err);
}
});
你也可以根據條件查詢數據,微信小程序提供了 db.command 來處理這些操作符,支持如下:
-
gt():大於 -
lt():小於 -
gte():大於等於 -
lte():小於等於 -
eq():等於 -
neq():不等於 -
in():在某個數組內 -
and():多個條件聯合
如果我們想要獲取 users 表中 city = '成都' and age > 25 的用户
db.collection('users').where({
age: db.command.gt(25),
city: "成都"
}).get({
success: res => {
console.log('查詢結果', res.data);
},
fail: err => {
console.error('查詢失敗', err);
}
});
新增數據
在雲數據庫中插入數據使用 add() 方法。你可以將數據以對象的形式傳入,並且雲數據庫會自動生成 _id, _openid。
const db = wx.cloud.database()
db.collection('users').add({
data: {
name: '張三',
age: 25,
city: '成都',
},
success: res => {
console.log('數據插入成功', res);
},
fail: err => {
console.error('數據插入失敗', err);
}
});
更新數據
更新數據使用 update() 方法,可以根據 _id 來指定要更新的文檔並修改某些字段的值。
const db = wx.cloud.database()
db.collection('users').doc('文檔ID').update({
data: {
age: 26,
},
success: res => {
console.log('數據更新成功', res);
},
fail: err => {
console.error('數據更新失敗', err);
}
});
刪除數據
刪除數據使用 remove() 方法,刪除指定 _id 的數據。
const db = wx.cloud.database()
db.collection('users').doc('文檔ID').remove({
success: res => {
console.log('數據刪除成功', res);
},
fail: err => {
console.error('數據刪除失敗', err);
}
});
一些小坑
雲數據庫更多操作可以查看官方文檔
雲數據庫看似很爽,但存在一些很隱蔽的坑,大概如下:
- 微信雲數據庫的查詢操作默認每次最多返回 20 條數據。如果你想查詢更多數據,必須進行分頁查詢,使用
skip() 和 limit() 進行分頁操作。你需要自己控制分頁邏輯,每次獲取一頁數據,直到沒有更多數據為止。 - 雲數據庫支持的查詢條件比較簡單,適用於大部分常見的需求,但也有一些限制。比如不支持正則查詢,所有的查詢都需要通過明確的字段條件進行。無法直接執行 OR 查詢,只能通過多個條件查詢。複雜的邏輯需要通過多個 where 調用或者在查詢後手動合併結果。
- 雲數據庫不支持真正的批量寫入操作,如批量更新、批量刪除等。如果需要進行大量數據的批量處理,可能需要循環處理每一條記錄,且會有一定的性能開銷。
- 雲數據庫採用的是強一致性模型,意味着每次寫操作(如
add、update)會確保數據在全局範圍內同步一致。如果你需要對數據進行併發寫操作(如多人同時修改數據),需要特別注意數據衝突的問題。如果多個用户同時修改同一條數據,可能會出現衝突,雲數據庫本身不提供衝突解決機制,需要你自己處理相關的業務邏輯。
完成開發後
備案與認證
在微信小程序正式上線前,需要完成 備案 和 認證 兩個重要步驟。
小程序備案
備案流程共分為三步:
- 補充小程序基本信息:包括名稱、圖標、描述等。
- 設置主營類目:選擇小程序所屬的業務類別,確保符合微信的運營規範。
- 提交審核:首先由騰訊進行審核,審核通過後提交至管局進行最終備案。
備案通過後,小程序才具備發佈正式版本的資格,否則無法正常對外運營。內容不復雜,個人主體提供下身份證,個人信息,郵箱那些基本就可以了
當天或者第二天騰訊就會打電話過來,不會有太多問題,主要就是核對下個人信息是否準確,詢問你姓名,身份證後六位,要審核的小程序名字,他的功能那些
中間突然問了個生肖,估計是為了防止第三方備案
備案主要卡在管局那邊,通常需要三五天到一星期,不會對小程序的內容進行審查,因此也可以在開發前進行備案,可以有效節省時間
小程序認證
認證是為了確保小程序主體的合法性和運營合規性。微信會委託 第三方審核機構 對以下內容進行審核:
- 主體真實性:核驗個人或企業的身份信息。
- 行業資質有效性:檢查小程序從事的業務是否符合相關行業要求。
- 命名合規性:確保小程序名稱符合微信命名規則。
- 線上服務可用性:測試小程序功能是否能正常使用。
個人認證的費用為 30 元,企業認證的費用為 300 元/年。只有通過認證後,小程序才允許被 分享 和 搜索,否則僅能通過掃碼或直接訪問進行使用。
最後
在微信開發者工具中,開發者可以直接 上傳 代碼。上傳後,代碼會出現在 版本管理 → 開發管理 頁面,確認無誤後即可提交審核。
在提交審核之前,務必 充分測試 小程序的功能和穩定性。因為 一旦審核通過,代碼就可以正式發佈(前提是已完成備案/認證)。如果提交了尚未經過完整測試的版本,可能會影響用户體驗,甚至導致線上 bug。
審核過程通常較快,一般 1 個工作日內 即可完成。不過需要注意的是,小程序發佈後如果在 90 天內未完成備案,將無法繼續使用。因此,建議 等備案完成後 再進行正式發佈,以免因備案問題影響小程序的正常運營。
至此,從 註冊 微信小程序,到 開發、調試,再到 備案與認證,整個流程基本走完了。如果你是第一次開發小程序,可能會覺得過程繁瑣,但實際上,微信提供的雲開發、開發者工具等已經大大降低了開發門檻,
雖然微信的文檔依然依託答辯
當然,技術只是基礎,小程序最終能否成功,還是要看產品的價值和用户體驗。如果只是想嘗試一下小程序開發,那雲開發是個不錯的選擇,能省去服務器的成本和後端開發的麻煩。但如果希望深入發展,還是建議結合自己的需求,考慮是否需要自建後端,或者使用更靈活的技術方案。