ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

不带后台的微信小程序商城源码:结构拆解与二次开发全攻略

不带后台的微信小程序商城源码:结构拆解与二次开发全攻略 简介这是一套开箱即用的微信小程序商城前端源码面向小程序初学者、快速原型开发者及教学实践者解决无后台依赖下构建完整电商展示与交互流程的需求。资源包含172个文件以38个JS逻辑文件实现业务控制、23个WXML模板定义页面结构、26个WXSS样式文件保障UI统一辅以55张PNG图标与轮播图素材整体压缩包仅907KB轻量易读易改。已有618人学习下载适合用于课程设计、毕业项目或小程序入门实战。源码覆盖商城核心模块支持客服电话与运费策略配置、模板消息对接、用户/商品/分类/品牌/轮播图/订单/促销等九大管理界面所有页面均提供真实截图预览如主页、购物车、支付页、订单确认页并内置showdown.js等实用工具脚本目录结构清晰模块职责分明便于理解小程序MVVM架构与组件化开发逻辑。 做微信小程序商城开发的朋友应该都在各种资源站、GitHub、博客分享里搜到过这类标题微信小程序-商城网站源码(不带后台)。我最早看到这类资源的时候也愣了一下什么叫不带后台下载下来一看明白了——整个项目里没有管理后台的代码商品数据是写死的静态JSON购物车用的是本地缓存用户登录走的是模拟流程支付基本就是调一下API发个演示请求完事。说白了这就是一个纯前端小程序壳子把商城的前端流程完整跑通了后端系统一概不涉及。这种源码到底有没有用我的答案是分情况。如果你只是练手、做毕业设计、给客户出静态演示demo、或者想快速上手微信小程序的整体开发流程这类源码反而是高效的起点结构不复杂没有一堆后端服务要本地启动克隆下来就能跑。但如果你指望它直接商用那基本不现实原因后面我会详细说。我前前后后接过几个小程序商城的单子也自己从这种“不带后台”的源码改过项目这里面的门道、坑和实操经验这篇一份全说清楚。不管你是刚入行的小程序新手还是想拿这种源码做改造的开发者都建议把这篇看完再动手。1. 先搞清楚不带后台的商城源码到底长什么样拿到这类源码第一件事不是急着改代码而是要搞清楚它的数据从哪里来、登录怎么走、状态怎么存。这三个问题弄明白了你才算真正“看懂”这份源码。1.1 没有后台不等于没有数据数据都在前端很多刚接触小程序的人容易误解以为不带后台就是没有数据。实际上数据全在项目里。最常见的是三种形态第一种是直接用JS文件导出JSON对象比如在/data/goods.js里写module.exports { goodsList: [...] }页面通过require引入这些数据然后渲染到界面上。这种方式最简单粗暴一眼就能看懂数据结构。第二种是把数据放在本地文件里比如goods.json然后用wx.request去请求一个本地路径。这里要特别注意微信小程序在真机上是不允许直接请求本地文件的只支持请求网络接口所以这种写法在开发者工具里能跑一上真机就白屏或报错。第三种是用云开发把商品集合放在云数据库里前端通过wx.cloud.database()API去读取。但严格来说云开发算半个后台因为它有云函数和数据库只是不需要你自己搭建服务器。市面上标注“不带后台”的源码通常指前两种第三种一般会单独标注“云开发版”。这三种形态对应着不同的改造难度。如果你想往里面加数据、改价格、换图片第一种最方便直接改JS就行第二种要看它请求的路径是不是合法域名需要配置第三种则是把数据放到了云端管理起来反而方便但需要开通云开发。1.2 这类源码适合谁又不适合谁我这些年接触下来找“不带后台”商城源码的基本是三类人第一类是纯学习的小白。刚从HTML/CSS/JS过渡到小程序开发想看看一个完整的商城页面是怎么写的、页面跳转是怎么做的、tabBar怎么配置这类源码结构简单能直接告诉你答案比文档教程直观得多。第二类是做毕业设计或课程设计的学生。这类项目需求通常只要求“能演示”不带后台反而省事不需要搭环境仓库里一拉运到微信开发者工具就能跑答辩演示完全够用。第三类是接项目的开发者。比如客户先要看个demo原型确认风格和功能了再谈后端开发这时候直接用现成源码改UI效率极高可能一晚上的功夫就出图了。至于不适合的人群也很明确想直接开网店做生意的老板想把小程序卖给客户然后收维护费的开发者这类源码完全撑不住。原因无非是没有订单系统、没有用户管理、没有商品管理、没有支付回调。你在demo里看到的商品列表可能只有五六个商品写死在文件里没有后台意味着没有运营入口连改个商品图片都得改代码重新发布版本这在真实业务里是不可接受的。说白了不带后台的源码是很好的“练习册”和“原型工具”但它不是“成品”。你要做的是基于它二次开发而不是拿来即用。2. 目录结构这样搭后面写代码能省一半烦恼很多新手拿到本项目恨不得马上打开app.json改两行看看效果我建议你先沉下心把目录结构摸一遍。一份好的商城源码目录结构能看出作者的规划思路这份直观也会影响你后续改动的效率。2.1 一个标准的商城小程序目录应该有哪些部分虽然每份源码的目录名称会有差异但大体上逃不出这几层pages/页面目录所有可见页面都放在这里。商城小程序一般有首页、分类、购物车、我的这对应tabBar四个底部导航还有商品列表页、商品详情页、搜索页、订单确认页、订单列表页等等。components/组件目录放置可复用的自定义组件。比如商品卡片、数量选择器、倒计时组件、空状态占位组件。组件化的设计会让首页和商品列表页复用同一个商品卡片模板不用重复写样式。utils/工具函数目录。常见的request.js网络请求封装、auth.js登录状态管理、cart.js购物车本地存储操作、format.wxs价格和日期格式化都在这。data/或mock/静态数据目录。不带后台的源码这里基本就是整个项目的“数据库”。static/或assets/静态资源目录放图标、默认图、一些本地图片。app.js全局逻辑入口主要做全局数据定义、登录态检查、版本更新提示。app.json全局配置页面路由、窗口样式、tabBar、分包配置都在这。app.wxss全局样式表。我强烈建议你把utils/request.js打开看看这是整个项目是否便于二次开发的关键。官方仓库里常见的封装方式是这样的// utils/request.js const BASE_URL https://api.example.com function request(url, method GET, data {}) { return new Promise((resolve, reject) { wx.request({ url: ${BASE_URL}${url}, method, data, header: { Content-Type: application/json }, success(res) { if (res.statusCode 200) { resolve(res.data) } else { reject(new Error(请求失败${res.statusCode})) } }, fail(err) { reject(err) } }) }) } module.exports { request }这个封装很简单但留好了扩展点。不管以后要加token、加拦截器还是换成云开发都只需要改这一处。如果你拿到的源码里压根没有request封装而是散落在各个页面里的wx.request那这份源码的质量大概率不高改造起来会很痛苦。2.2 数据层拆出来是好习惯哪怕没有后台也一样我改造过几份商城源码之后最大的体会是无论有没有后台都要把数据访问和页面逻辑分离。不带后台的源码最容易出现的问题就是页面里直接写死数据// 不推荐的写法 Page({ data: { goodsList: [ { id: 1, name: 商品A, price: 19.9 }, { id: 2, name: 商品B, price: 29.9 } ] } })这种写法短期内没什么问题但项目一旦变大你会有十几个页面都要显示商品信息每个页面都粘一份数据不一致就是迟早的事。合理的做法是把数据源集中在data/goods.js里页面require引用// data/goods.js const goodsList [ { id: 1, name: 商品A, price: 19.9, image: /static/images/a.png }, { id: 2, name: 商品B, price: 29.9, image: /static/images/b.png } ] module.exports { goodsList }然后页面里const { goodsList } require(../../data/goods) Page({ data: { goodsList: [] }, onLoad() { this.setData({ goodsList }) } })这样做的好处在后期特别明显。假设你想把静态数据源换成云开发数据库接口只需要在data/goods.js里改成异步请求页面的展示代码完全不用变数据结构保持稳定界面层就永远不需要频繁改。还有一点值得养成习惯用storage存购物车和用户信息的时候一定要用统一的key前缀比如cart_list、user_info。之前有人在项目里用了carts和cartList两个key页面间数据就会偶尔同步不上排查起来特别费劲。约定统一命名至少能少踩一半缓存的坑。3. 核心页面逐个拆解首页、商品列表、商品详情、购物车商城类小程序的页面虽然多但核心就那几个。把首页、商品列表、商品详情、购物车这四个页面吃透了整个商城的骨架就到手了。我一个个过注意听我说的坑因为这些坑我自己都踩过。3.1 首页轮播图、金刚区和推荐位的数据流设计首页是商城的面子一般由轮播图、金刚区图标、活动楼层、商品瀑布流等部分组成。不带后台的源码里首页数据通常是写在onLoad里的。你先别急着改样式先想清楚首页需要哪几类数据banner列表、navIcon列表、活动商品列表。这些数据分类存储后续改动才方便。比如轮播图数据很多源码给的是远程图片URL。在开发者工具里能显示但在真机上往往会因为域名没配置到downloadFile合法域名而加载不出来。如果你接手的是这种源码要么把所有图片替换成本地图片要么在公众平台后台加上域名白名单。本地图片放在static/banner/下在data里引用绝对路径/static/banner/1.jpg即可。首页还有个容易忽略的点是onShow与onLoad的区别。商城首页通常需要展示购物车角标角标数量是存在本地缓存里的。如果你只在onLoad里读取一次用户加购后切回首页角标数量不会变。正确做法是在onShow里重新获取购物车数据并更新角标。onShow() { const cartList wx.getStorageSync(cart_list) || [] const totalCount cartList.reduce((sum, item) sum item.count, 0) wx.setTabBarBadge({ index: 2, text: totalCount 99 ? 99 : String(totalCount) }) }这里有个体验细节如果角标数量为0最好调用wx.removeTabBarBadge移除角标否则数字0一直挂在导航栏上看起来非常怪。3.2 商品列表和商品详情参数传错就是黑屏商品列表页通常有两种入口一种从首页金刚区或活动楼层点进来一种从分类页点进来。列表页通过接收categoryId来筛选商品数据。页面跳转时参数传递用的是URL拼接查错也基本从这开始。下面这种写法很常见// 首页跳转到商品列表页 wx.navigateTo({ url: /pages/goods-list/goods-list?id${item.id}name${encodeURIComponent(item.name)} })接收参数时onLoad(options) { this.setData({ categoryId: options.id }) this.loadGoods() }注意一点如果商品名里有中文或特殊符号跳转前一定要encodeURIComponent编码处理否则在某些手机上会导致跳转后参数被截断页面拿不到完整参数呈现出来的就是空白或报错。这也解释了一部分人遇到的黑屏问题。商品详情页相对复杂除了接受商品id外还要处理SKU选择、库存判断、加入购物车、立即购买。在很多不带后台的源码里SKU其实是假的只是前端做了个简单的规格弹窗选中某个规格就弹一下“已选红色/XL”并不会真正区分库存。这个问题不大演示足够了但你要心里有数——后续接真实后端时SKU数据结构的对接是逃不掉的一般需要按“可选规格组 规格组合对应SKU 价格库存”的结构来设计。商品详情页还有一个性能优化的点就是onLoad里不要一次性setData一坨巨大的对象。如果你有几十张商品详情图片全部放到一个detailImgs数组里一次性setData页面渲染会很卡。优化的做法是分页加载先渲染前5张滑动到底部时再追加后续图片。这个技巧在真实项目里很有用。3.3 购物车本地缓存方案的关键操作不带后台的购物车实现方式几乎全是基于wx.setStorageSync和wx.getStorageSync。不要小看这一块踩坑概率极高。购物车最核心的操作是增删改查加购先读缓存判断商品是否已存在存在则数量累加不存在则push进去。修改数量遍历数组找到对应id修改count字段。删除过滤掉对应id。计算总价reduce累加所有勾选商品的price * count。每次操作后记得setStorageSync写回缓存。这里很容易出问题的地方是修改数量后忘记写回。我见过不止一次页面上显示“ - ”按钮点了没反应排查半天发现是商品数量改了缓存没有同步。举个例子一个完整的修改数量方法应该是changeCount(e) { const { id } e.currentTarget.dataset const { type } e.currentTarget.dataset let cartList wx.getStorageSync(cart_list) || [] const index cartList.findIndex(item item.id id) if (index -1) return if (type minus) { if (cartList[index].count 1) { wx.showToast({ title: 最少购买一件, icon: none }) return } cartList[index].count-- } else { cartList[index].count } wx.setStorageSync(cart_list, cartList) this.setData({ cartList }) this.calcTotal() }购物车还有一个注意点商品数据可能会变。缓存里存了商品价格和商品图片如果你在编辑端改了价格用户本地缓存的旧价格不会自动更新。解决思路是登录小程序时做一次缓存同步拉取最新的商品信息覆盖缓存中的价格字段。不带后台的源码通常没有这层逻辑但你心里得留着这个坑。4. 订单流程、支付环节、用户体系能演示但不能商用的大硬伤商城小程序逃不开订单、支付和用户。这部分恰恰是不带后台源码“水分”最大的地方也是真想商用必须要补的功课。4.1 订单流程的模拟实现方式不带后台的商城订单流程一般是这样的从购物车勾选商品或商品详情页点立即购买跳到订单确认页确认页展示商品清单、收货地址、金额明细点提交订单后生成一个订单号然后跳到“支付页”。这个流程走到支付这一步通常就是做个假按钮点一下弹个toast“支付成功”。订单数据会存到本地缓存形成一份“订单历史”。说得更直白一点这份源码里订单的所有状态都是本地维护的没有任何服务器来验证订单是否真实有效。对演示来说流程完整即可但等你要接入后端时这一块基本要全部推翻重写。真要做订单对接有几个关键接口是必写的创建订单接口、预支付接口统一下单、支付回调接口、订单查询接口。前端的页面可以复用源码里的样式和交互但是订单号生成、金额计算这些幂等相关的逻辑一定要放在后端。不要再拿本地时间戳当订单号并发一高就会撞单。4.2 微信支付这个坎没有后台是真的迈不过去这是整个商城源码里影响最大的一个“硬伤”微信支付必须要有后端服务器来参与签名。微信支付的官方流程是前端调起支付需要传入timeStamp、nonceStr、package、signType、paySign这五个参数而这些参数必须由开发者服务器调用“统一下单”接口并获得返回结果后生成。小程序端直接调wx.requestPayment是拿不到合法参数的。所以不带后台的源码支付功能永远只能停留在“假支付”演示层面。你可以在开发者工具里弹个模拟支付面板但点到真机上它不可能调起真实的微信收银台。想接真实支付最轻量的方案是用云开发云函数里可以调用微信支付的云调用能力。云函数拿到用户的身份信息和商品金额在云端完成签名并返回支付参数前端再发起支付。这样比起自己搭建完整的后端服务要省事得多适合个人开发者和微小业务。还有一点必须注意微信小程序对虚拟支付管控很严。如果你卖的是虚拟商品比如视频课程、电子书、在线服务iOS端是无法使用微信支付完成的。这是平台规则跟用什么技术方案都无关。商城源码里如果设计的是实物商品这部分风险较小但如果你卖的是会员之类的虚拟服务建议对照微信官方的小程序虚拟支付规则看一遍别等上线审核被打回来才想起来。4.3 用户体系没有后端怎么实现登录正常的小程序登录是前端wx.login拿到临时code发给后端后端拿着code去微信的开放接口换openid和session_key然后生成自定义登录态token返回给前端。很明显没有后端这个过程也走不通。不带后台的源码通常用两种方式绕过登录一是直接存一份“假用户信息”到本地缓存比如登录页让你输个昵称保存就完事二是用微信的“头像昵称填写能力”让用户主动填写头像和昵称前端拿到后存进 storage。这里要提醒一下如果需要拿用户的手机号必须经过后台。手机号快速验证组件返回的动态token必须由服务器向微信接口换取真实手机号。没有后台这一步无法完成。所以如果你做的商城必须依赖手机号做会员体系这个功能在纯前端方案里是假不了的。如果是用云开发则可以通过wx.cloud.callFunction在云函数里使用cloud.openapi的能力完成登录态换取和手机号解密。这一方案比纯前端强得多介于“不带后台”与“带后台”之间适合中期改造。5. 打包上线阶段我整理的调试记录开发完不代表结束小程序还得过审核、正式上线。这一环节的问题比写代码时更现实。很多新手在开发者工具里跑得好好的一传代码就各种问题我挑几个高频的坑详细说一下。5.1 手机上看白屏第一件事查这个真机白屏问题我遇到太多次了。最典型的场景是开发者工具一切正常手机扫码预览页面一片空白console里也没有明显报错或者只有一些无关紧要的警告。排查顺序很重要。先看app.json里注册的第一个页面路径对不对。小程序启动默认加载pages数组中的第一项如果这个路径写错整个小程序直接白屏但工具里不一定报错。然后看页面onLoad里有没有运行时报错特别是setData里传了 undefined 或者对象层级不对真机上容易直接终止掉页面渲染。还有一个常见问题代码里使用了基础库之外的API但project.config.json里设置的libVersion太低。真机上会直接调不到这个API表现就是页面某个区块渲染不出来。建议把libVersion调整到与最近版本相差不要超过三个月的版本既能用上新能力又避免在太多老版本上不兼容。最后就是网络请求问题。真机请求必须走HTTPS且请求域名已备案并配置到request合法域名。很多山寨源码里写的接口域名是假的开发者工具开启“不校验合法域名”之后能跑真机上所有请求全部失败页面自然会白屏。5.2 顶部导航栏高度和小程序的刘海屏适配顶部导航栏高度是很多商城页面自定义头部时必踩的坑。如果你使用了自定义导航栏在app.json或页面json里设置navigationStyle: custom那么你的页面顶部需要避开状态栏和胶囊按钮区域。获取状态栏高度和菜单按钮位置有一套固定代码const systemInfo wx.getSystemInfoSync() const menuButton wx.getMenuButtonBoundingClientRect() const navBarHeight (menuButton.top - systemInfo.statusBarHeight) * 2 menuButton.height const statusBarHeight systemInfo.statusBarHeight这套逻辑的基本原理是胶囊按钮的上边框到状态栏下沿的距离约等于胶囊按钮下边框到导航栏下沿的距离。乘以2再加胶囊高度就是自定义导航栏的总高度。这个计算方式在绝大多数机型上都适用你在安卓、iOS、各种刘海屏水滴屏上都可以用同一套代码处理。要特别注意的是某些安卓机型的wx.getSystemInfoSync在横屏或分屏模式下会返回异常值实现时最好加一层兼容判断取值异常时回退到默认值。5.3 分包和异步化的配置要点商城类小程序如果商品图片多、页面多很容易触达主包2MB的体积限制。这时候就必须使用分包。app.json里配置分包{ pages: [ pages/index/index, pages/category/category, pages/cart/cart, pages/mine/mine ], subPackages: [ { root: pagesGoods, pages: [ goods-detail/goods-detail, goods-list/goods-list ] }, { root: pagesOrder, pages: [ order-confirm/order-confirm, order-list/order-list ] } ] }主包只保留tabBar页面和公共组件、公共工具其他页面全部放进分包主包体积立刻就能降下来。分包异步化是个进阶优化点。比如商品详情页是从首页导航跳过去的首页属于主包商品详情页属于分包A。如果使用者网络情况一般跳到分包页面时就需要下载分包A的代码如果加载速度慢就会出现短暂的白屏或loading。分包异步化允许你预加载或者延迟加载一些分包资源比如在首页通过wx.loadSubpackage提前预下载下一个包。配合缓存策略可以明显改善跨包跳转时的加载体验。5.4 防止截屏、前端上传文件等特殊需求的做法有客户提过“小程序里不能截屏”的需求这实际上不是要监听截屏行为而是给页面做一次防截屏处理。微信提供了wx.setVisualEffectOnCapture这个API调用后用户截屏时页面内容会被隐藏只有设置的占位内容显示出来。这个API在iOS上的适配相对较好Android上不同机型的表现略有差异所以不要把它当作绝对的安全措施只能说是增加截屏的难度。关于前端直接上传文件到云端存储比如上传到某个对象存储服务在没有后台的情况下确实有一个曲线方案在云函数中生成一个临时密钥然后前端拿着临时密钥直接上传到对象存储。这样不需要自己搭一个上传代理服务。要注意的是临时密钥需要配置有效期和存储路径的权限范围否则容易产生安全隐患。6. 常见问题速查表与这几年的实操心得这部分我把平时开发中被问得最多的问题整理成了一张表另外补充一些自己的实操经验。6.1 常见问题速查表问题现象根本原因解决方案开发者工具运行正常手机预览白屏常见于合法域名未配置或页面路径错误真机调试看Network面板确认所有请求返回正常检查app.json首屏路径轮播图/商品图真机上加载不出来图片域名未加入 downloadFile 合法域名把图片换成本地资源或在公众平台配置下载域名点击tab切换瞬间白屏再恢复页面初始化耗时较长或过度使用同步缓存用分包预加载减少onLoad同步耗时操作或使用异步缓存API Loading占位付款按钮点击无反应或提示缺少参数微信支付需要后端签名纯前端跑不通改用云开发云函数实现统一下单或自建后端服务TextView/input层级被原生组件盖住原生组件层级问题使用cover-view覆盖或升级到同层渲染方案键盘弹起时输入框被挡住或页面错位未做键盘避让处理在page.json中配置disableScroll监听adjust-position事件调整布局“不校验合法域名”关闭后请求全部失败请求域名为http协议或未备案转换成https并接入已备案域名预览整个包体积过大传不上来主包超过2MB把非tabBar页面全部移入分包压缩图片资源自定义导航栏在刘海屏上错位未正确计算状态栏高度和胶囊位置按getMenuButtonBoundingClientRect动态计算用户token过期后所有接口失败没有统一处理登录态失效在request.js中加入402/401拦截统一跳转登录页这张表不光是给小白的很多时候你做了一两年项目遇到某些现象第一反应也可能是“改样式”或“重新编译”但根因往往是上述这些配置问题。建议截图存一份排查的时候先过一遍。6.2 几条干货心得第一改这种源码前先花半小时整理一份“数据字典”。打开data/或者utils/里所有的数据文件把商品字段、订单字段、用户字段列出来理解每个字段的含义。这事儿看起来费时间但真的能帮你省后期好几个小时的排查时间。尤其是那些命名不太规范的字段比如img、pic、image混用的不整理清楚后面改到一半就会懵。第二不要在setData里传包含大量函数的对象。小程序的setData是通过逻辑层和渲染层之间的桥接协议传输数据的函数不会被正确序列化传了也是白传还可能引起性能警报。数据模型保持纯数据所有方法都挂在Page或组件的宿主上。第三购物车、收藏列表这种频繁读写的功能建议封装成独立模块。比如utils/cart.js对外暴露getCartList()、addToCart(goods)、updateCount(id, count)、removeFromCart(id)等方法。不要在每个页面里都直接操作storage字符串一旦你以后要换成wx.syncCloud或者请求后端接口只需要改这个模块内部实现其他页面完全不用动。这是带后台改造时性价比最高的一次重构。第四也是最重要的学会给自己留“后门”。不带后台的源码接后端的时候切接口是最麻烦的。我习惯在utils/config.js里加一个总开关module.exports { // true: 使用本地模拟数据false: 使用远程接口 USE_MOCK: false, BASE_URL: https://your-api.example.com }每个页面的数据获取逻辑都判断这个开关。开发阶段用MOCK数据后端就绪后把开关切掉即可。加上这个逻辑后开发效率会高不少而不是接接口时把页面逐个翻出来改。结尾最后说点个人体会吧。我见过太多人拿着这种“不带后台”的商城源码试图直接改成商用项目最后都被支付、订单、后台管理这类问题卡得死死的。但也正因如此这类源码在学习和原型阶段的价值反而被低估了。你只要抱着正确的预期去用它会发现它是一份极其难得的前端实践教程——小程序的核心页面、组件、路由、缓存、交互一整套流程都摆在你面前拿来拆解、练习、改造成自己的项目成长速度比自己从零写快得多。我记得自己第一次完整啃完一份商城源码再回去看小程序官方文档时很多概念一下就通了。如果你也能把它当作“题目”而不是“答案”哪怕最终没有成功上线你学到的东西也一定不会亏。如果后续有空我打算再整理一篇具体的改造记录怎么把这样一个纯前端商城改成云开发版包括登录、支付、商品管理完整的链路实际操作下来踩过的坑也不少那篇可能会更长。先到这里。本文还有配套的精品资源点击获取
返回列表