从源码到上线:茶叶商城微信小程序改造实战要点
简介这是一份微信小程序开发实战案例源码包以茶叶商城为完整业务场景帮助小程序初学者、前端开发者快速掌握电商类小程序的实现思路。压缩包共有178个文件以WXML、WXSS、JS、JSON等核心文件构建页面结构、交互逻辑与配置项并搭配PNG图片素材、RB辅助文件及大量小尺寸代码文件整体大小为3.29MB目录结构清晰便于按模块查阅。目前已有347人学习。案例集成了商品展示、购物车、订单管理、用户登录等常用电商模块代码中覆盖API调用、页面路由、生命周期管理、数据双向绑定、性能优化以及微信分享、支付等生态能力并包含异步加载、分页、缓存策略等实战细节。通过学习这套源码读者既能理解小程序从界面搭建到业务闭环的完整流程也能借鉴真实项目的分层设计与功能组织方式为独立开发移动端应用打下扎实基础。1. 茶叶商城小程序源码照着改比自己从零写更快电脑里存着一份「微信小程序开发-茶叶商城案例源码.zip」时第一反应通常是急着解压。茶叶商城这类小程序案例确实值得打开商品列表、分类、购物车、订单这些电商基础链路都已跑通刚好能用来练微信小程序开发顺便把源码里能复用的工具函数抄进自己的项目里。但案例源码不是压完就完事的文件里可能有写死的appid、Mock数据、过时的接口域名你得会改才能把它变成自己的项目。这篇从工程结构拆到购物车状态管理最后说怎么跑真机、过审核争取让你拿到zip后一天内改成能用的版本。2. 拆解茶叶商城源码的项目结构与工程配置2.1 源码包里的目录怎么读拿到zip先别急着全部解压先看文件体积。几百KB的多是纯前端Demo1MB以上一般带了图片素材或云函数目录。茶叶商城案例的目录通常长这样tea-mall/ ├── app.js ├── app.json ├── app.wxss ├── project.config.json ├── pages/ │ ├── index/ # 首页商品流 │ ├── category/ # 分类页 │ ├── cart/ # 购物车 │ ├── order/ # 订单列表 │ └── mine/ # 个人中心 ├── components/ │ ├── goods-card/ # 商品卡片组件 │ └── tabbar/ # 自定义TabBar如果有 ├── utils/ │ ├── request.js # 网络请求封装 │ ├── cart.js # 购物车数据操作 │ └── util.js # 时间格式化等工具 ├── images/ └── data/ └── goods.js # 模拟商品数据这段目录对应微信小程序开发里的标准分区pages只放页面components只放可复用组件utils放纯逻辑。我看别人源码时会先打开project.config.json确认appid是不是测试号再打开app.json看注册了哪些页面这能避免导入后白屏。提示案例源码里没有的目录不要硬建小程序页面只要写在 app.json 的 pages 里就会被编译没写的目录不影响运行。2.2 从app.json理解页面注册与TabBar导航茶叶商城这类电商项目通常有4个底部Tab首页、分类、购物车、我的。源码里app.json的常见写法是{ pages: [ pages/index/index, pages/category/category, pages/cart/cart, pages/mine/mine, pages/order/order, pages/goods/goods ], window: { navigationBarBackgroundColor: #a47c5b, navigationBarTitleText: 茶叶商城, navigationBarTextStyle: white, backgroundTextStyle: dark, enablePullDownRefresh: false }, tabBar: { color: #7f7f7f, selectedColor: #a47c5b, list: [ { pagePath: pages/index/index, text: 首页 }, { pagePath: pages/category/category, text: 分类 }, { pagePath: pages/cart/cart, text: 购物车 }, { pagePath: pages/mine/mine, text: 我的 } ] }, style: v2, sitemapLocation: sitemap.json }pages数组第一个元素是启动页tabBar的list必须是2到5项pagePath要在pages里注册过text不能为空。茶叶商城这里配色是茶色如果你换成自己的品牌色需要同时改navigationBarBackgroundColor和tabBar.selectedColor不然状态栏字体颜色会看不清。另外订单页通常不在tabBar里而是从“我的”页面跳进去的二级页面所以pages里注册了但tabBar没列这也是源码里的正常设计。2.3 开发环境准备与源码导入本地要装微信开发者工具稳定版就好。导入源码包我一般不用“导入项目”而是先新建一个空白小程序项目再把解压的源码覆盖进去这么做能避开project.config.json里旧appid导致的“项目目录无效”问题。具体步骤微信开发者工具登录后新建小程序项目目录选空文件夹tea-mallAppID先用测试号。关闭工具把源码包内所有文件拷贝进tea-mall覆盖原有内容。重新打开项目工具会自动读取project.config.json配置如果提示appid不匹配就去project.config.json里改“appid”字段。点“编译”。如果只看到首页白屏打开调试器看Console常见错误是goods.js路径写错或图片路径404。这一步花不了5分钟但能让你后续改代码时不纠结环境问题。改完记得在project.config.json里确认compileType还是“miniprogram”避免部分工具版本默认打开的是插件模式。3. 茶叶商品列表与分类页数据结构与渲染逻辑3.1 商品数据从哪里来data目录还是后端接口茶叶商城案例一般有两种商品数据组织方式一种是把商品直接放在data/goods.js里导出JS数组另一种是用request.js请求后端返回。初学者很容易混页面里直接require商品数据可以秒开但没法做分页走接口虽然要处理loading状态但更接近生产环境。我的做法是阅读源码时只把data目录当Mock真机联调时替换成真实接口。goods.js里每件茶叶商品大概长这样module.exports [ { id: 1, name: 明前龙井 50g, subtitle: 2024年头采豆香明显, price: 128, // 注意这里存的是元不是分 originalPrice: 168, image: /images/goods/longjing.png, category: 绿茶, sales: 326, stock: 50 } ]这段代码里price直接用元到了计算购物车总价时要小心浮点误差后面第4章会提到。category字段用来做分类页联动如果你的商品不止茶类也可以改成categoryId关联分类表。案例源码里没有单独的分类表时建议补一个category.js因为分类页要的不是“绿茶/红茶/白茶”这种写死数组而是能对应到具体商品列表的结构。3.2 分类导航与商品列表联动分类页通常是左侧一列分类右侧一个滚动商品列表。wxml大致这样view classcategory-page scroll-view classleft-menu scroll-y block wx:for{{categories}} wx:keyid view classmenu-item {{currentIndex index ? active : }} bindtaponSelectCategory>Page({ data: { categories: [], goodsList: [], currentIndex: 0 }, onLoad() { const goods require(../../data/goods.js) const categories this.dedupeCategories(goods) this.setData({ categories, goodsList: this.filterGoods(goods, categories[0].name) }) }, onSelectCategory(e) { const { index } e.currentTarget.dataset const name this.data.categories[index].name this.setData({ currentIndex: index, goodsList: this.filterGoods(this.goods, name) }) }, filterGoods(goods, categoryName) { return goods.filter(item item.category categoryName) }, dedupeCategories(goods) { const map {} goods.forEach(item { if (!map[item.category]) map[item.category] true }) return Object.keys(map).map((name, id) ({ id, name })) } })这段代码把数据筛选放在前端好处是素材少、切换快坏处是每次都要重新require和处理。建议在onLoad里把goods缓存到this.goods切换时从缓存里filter避免在onSelectCategory里再次require。参数说明currentIndex控制左侧菜单高亮必须在data里声明setData时会把新索引同步到视图。>Component({ properties: { item: { type: Object, value: {} } }, methods: { onTap() { this.triggerEvent(goDetail, { id: this.data.item.id }) } } })父页面用bind:goDetail接收就可以跳转详情。加载状态这块值得一提案例源码里多半没有做骨架屏但你改源码上线时一定要加。最简单的方式是在页面data里有一个loading字段初始为trueonLoad里数据到位后setData为falsewxml里用wx:if和wx:else切换骨架屏和正文。这里列几个我常用到的列表参数供你对照源码排查参数/事件值示例作用wx:keyid列表渲染时提高diff性能必填currentIndex0左侧菜单高亮索引scroll-y布尔值让scroll-view支持垂直滚动>const CART_KEY tea_cart function getCart() { return wx.getStorageSync(CART_KEY) || [] } function saveCart(cart) { wx.setStorageSync(CART_KEY, cart) } function addToCart(goods, count 1) { const cart getCart() const index cart.findIndex(item item.id goods.id) if (index -1) { cart[index].count count } else { cart.push({ id: goods.id, name: goods.name, price: goods.price, image: goods.image, count }) } saveCart(cart) return cart }这里用Storage不用globalData的原因Storage是持久化的而且可以跨页面和组件直接读取不需要每次走事件总线。要注意的是wx.setStorageSync有10MB上限纯购物车数据足够如果要存图片base64那就要换wx.setStorage异步接口或者只存文件路径。4.2 金额计算避免浮点精度坑茶叶价格是小数0.1 0.2在JS里等于0.30000000000000004案例源码里如果用price相加直出total结算时会出现8.999999这样的数字。我处理方式永远是转成整数分function calcTotal(cart) { return cart.reduce((sum, item) { return sum Math.round(item.price * 100) * item.count }, 0) } // 展示给用户时 function formatPrice(totalInCents) { return (totalInCents / 100).toFixed(2) }这段代码里把价格乘以100得到分加法后最后才除以100能保证总额没有累计误差。订单提交时传给后端后端也应按照“分”计算接口契约上写清楚单位。后面如果要做优惠券满减或折扣也全部基于分计算避免价格字段出现浮点污染。4.3 订单状态与订阅消息订单页常见的状态是待支付、待发货、待收货、已完成。案例源码的order数据模型里通常会带一个status字段我常用的状态枚举如下status含义操作0待支付取消订单、继续支付1待发货无操作2待收货确认收货3已完成再次购买4已取消删除订单支付完成后的通知早期案例里用模板消息现在必须改用订阅消息。要点是订阅消息每次用户操作只能授权一次你要在用户点击“下单”按钮时唤起授权而不是在支付完成回调里再请求。代码接近这样wx.requestSubscribeMessage({ tmplIds: [xxxxxxxxxxxxxxxxxxxx], success(res) { // res[xxxxxxxxxxxxxxxxxxxx] accept 说明用户同意 }, fail() { // 拒绝授权时不能打扰用户静默处理 } })注意tmplIds最多3个而且必须在小程序后台添加模板后才能拿到ID。源码里如果看到wx.requestSubscribeMessage多半要换成你自己的模板ID否则真机预览时授权弹窗会报错。5. 从案例源码到能发布的小程序验证与发布5.1 真机预览与接口域名配置本地开发时勾选“不校验合法域名”可以但体验版和发布版绝对不能用。登录小程序后台把接口域名配置进request合法域名必须HTTPS且ICP备案图片域名如果用了CDN也要加进downloadFile合法域名。我用真机预览的习惯是先开调试模式看Console确认每一条接口都返回再关调试走正式环境。5.2 分包加载茶叶商城也值得做商品详情、订单、个人中心这些都是低频页面放到主包会让首包体积变大。主包如果超过1.5MB就得分包。app.json里加一段配置{ subpackages: [ { root: packageOrder, name: order, pages: [pages/order/order, pages/orderDetail/orderDetail] } ] }把订单相关页面挪到分包后tabBar里不能引用分包页面所以订单入口要放在“我的”页面跳转。案例源码如果本身页面少得可怜不必强行分包等以后加了详情、评价、优惠券再拆也不迟。5.3 调试案例源码时的两个小坑图片403多半是图片域名没加到downloadFile合法域名tabBar不显示图标通常是因为tabBar的iconPath图片不存在工具不报错但不显示图标。源码里如果iconPath是空字符串只能自己补两张png。另外发布前把app.js里的调试日志开关关掉用wx.getUpdateManager()监听新版本提交审核时的截图要露出真实茶叶商品而不是Mock数据这些小细节才是案例源码能不能顺利转正的关键。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →