去年接手百战商城小程序项目时,商品数据还硬编码在前端JS文件里。每次运营修改价格或上下架商品,都需要重新发版小程序,这种开发模式存在三个致命问题:
经过技术评估,我们决定将商品数据迁移到微信云开发环境。这个改造的核心价值在于:
提示:云开发方案特别适合快速迭代的电商类小程序,从开发到上线最快只需2人日
改造前架构:
code复制前端小程序 → 硬编码JSON数据
→ 部分接口通过HTTP请求外部API
改造后架构:
code复制前端小程序 → 云函数 → 云数据库
→ 云存储(商品图片)
关键改进点:
创建goose集合时,我们采用电商场景通用字段结构:
| 字段名 | 类型 | 说明 | 索引 |
|---|---|---|---|
| _id | string | 商品ID | 主键 |
| name | string | 商品名称 | 文本索引 |
| price | number | 售价(单位:分) | 升序索引 |
| stock | number | 库存量 | - |
| images | array | 图片URL数组 | - |
| tags | array | 分类标签 | 多键索引 |
| isOnShelf | boolean | 上架状态 | - |
特别注意:
商品查询云函数goose_data需要处理以下几个关键问题:
javascript复制// 防御性处理页码参数
const page = Math.max(1, parseInt(event.page) || 1)
const pageSize = Math.min(100, parseInt(event.pageSize) || 10) // 限制每页最大100条
javascript复制const query = db.collection('goose')
.where({
isOnShelf: true // 只查询已上架商品
})
.field({
_id: 1,
name: 1,
price: 1,
image: { $arrayElemAt: ['$images', 0] } // 只取首图
})
javascript复制// 使用count先获取总数(用于前端分页器)
const countResult = await query.count()
const total = countResult.total
// 实际查询数据
const dataResult = await query
.skip((page - 1) * pageSize)
.limit(pageSize)
.get()
return {
data: dataResult.data,
total,
page,
pageSize
}
旧版HTTP请求:
javascript复制wx.request({
url: 'https://api.example.com/goods',
data: { page: 1 },
success(res) {
// 数据处理逻辑
}
})
新版云函数调用:
javascript复制const loadGoods = async (page = 1) => {
try {
const res = await wx.cloud.callFunction({
name: 'goose_data',
data: { page }
})
// 返回数据包含分页信息
return {
list: res.result.data,
total: res.result.total
}
} catch (e) {
console.error('商品加载失败', e)
wx.showToast({ title: '加载失败,请重试', icon: 'none' })
throw e
}
}
javascript复制Page({
data: {
loading: false,
hasMore: true,
page: 1,
goodsList: []
},
onReachBottom() {
if (this.data.loading || !this.data.hasMore) return
this.setData({ loading: true })
loadGoods(this.data.page + 1).then(res => {
this.setData({
goodsList: [...this.data.goodsList, ...res.list],
page: this.data.page + 1,
hasMore: this.data.goodsList.length < res.total
})
}).finally(() => {
this.setData({ loading: false })
})
}
})
问题1:云函数返回Permission denied
问题2:分页数据重复/缺失
javascript复制.orderBy('_id', 'asc') // 确保分页稳定性
xml复制<image
src="{{item.image}}"
mode="aspectFill"
lazy-load
/>
javascript复制// 在wxml中添加骨架屏
<block wx:if="{{!goodsList.length}}">
<!-- 骨架屏内容 -->
</block>
javascript复制let retryCount = 0
const loadWithRetry = async () => {
try {
return await loadGoods()
} catch (e) {
if (retryCount++ < 3) {
return new Promise(resolve => {
setTimeout(() => resolve(loadWithRetry()), 1000 * retryCount)
})
}
throw e
}
}
云函数增强版:
javascript复制// 支持名称模糊搜索
if (event.keyword) {
query.where({
name: db.RegExp({
regexp: event.keyword,
options: 'i'
})
})
}
前端调用示例:
javascript复制wx.cloud.callFunction({
name: 'goose_data',
data: {
keyword: '羽绒服'
}
})
数据库设计改进:
category字段categories云函数改造:
javascript复制if (event.categoryId) {
query.where({
'tags': _.in([event.categoryId])
})
}
接入云开发监控:
javascript复制// 在云函数中添加性能日志
const startTime = Date.now()
// ...业务逻辑...
const endTime = Date.now()
cloud.logger().log({
type: 'perf',
name: 'goods_query',
duration: endTime - startTime
})
这个改造项目让我深刻体会到云开发对小程序项目的提效作用。特别建议在数据查询层添加缓存机制,我们后续通过添加Redis缓存使商品列表查询速度提升了3倍。另一个经验是尽早建立完整的数据变更日志,这对后续排查问题非常有帮助