资讯动态

微信小程序源码二次开发实战:从Mock数据到请求封装

发布时间:2026/10/18 15:10:05 来源:尧图企业网站定制
简介这份源码合集收录了100个微信小程序项目的完整代码面向初学小程序开发或希望快速参考实战案例的开发者。内容涵盖基础组件、页面生命周期、数据绑定、wx.request网络请求及本地存储等核心知识点并涉及地图、支付、分享等常见高级功能代码结构清晰便于对照学习。压缩包约185.3MB文件类型以.wxml、.wxss、.js和.json为主分别承担页面结构、样式、逻辑与配置功能打包为zip格式。目前已有555人学习下载适合通过阅读真实工程理解小程序从启动到运行的完整流程。开发者可借助这些源码快速掌握JavaScript、WXML、WXSS三者的配合方式还能借鉴布局技巧、异步处理与性能优化思路为解决实际问题或拓展新创意提供参考。1. 这套微信小程序源码不是「看看就懂」是「改改就能用」很多开发者下载微信小程序源码第一反应是打开开发者工具看渲染结果盯着 page 文件夹半天真正要改业务时却不知道从哪下手。我拿到这套源码时也踩过同样的坑——但它和你想象中那种只有几个静态页面的 demo 不一样内置了可切换的 Mock 数据层、请求封装、预约流程闭环也就是说把前后端联调的那些边界问题提前处理好了。这套源码的定位是一套面向真实业务场景的小程序前端工程。适合两类人一类是刚接触小程序、想找一个结构干净的工程把环境跑起来的初学开发者另一类是已经会写页面、但是想在二次开发时少踩登录态、接口权限、数据缓存这些坑的实战派。无论你是要搭一个服务预约、工单提交还是活动报名的小程序这套代码都能作为起点直接往你的业务上靠。2. 项目全景与技术选型一个请求从「代码层」到「数据层」的两级路由2.1 这套源码能干什么这套源码做的是一个「社区服务预约」的场景用户在首页看到服务列表点某个服务进详情然后填写预约表单提交最后在「我的预约」里看到记录。功能不多但覆盖了小程序里最常见的四个技术主题列表页动态渲染对应wx:for和wx:key的数据驱动思路表单页收集用户输入对应事件冒泡和自定义数据携带网络请求的统一管理对应wx.request被封装后如何结合 Promise 做状态编排用户身份识别对应登录态在小程序端如何被临时保存、如何与后端对账。这四个主题可不只是页面写法的事。举个例子服务列表的加载如果不做 loading 状态和错误提示用户在弱网环境里点一下等十秒然后看到白屏很多人第一反应是「小程序卡死了」然后直接退出。源码里对每个异步操作都做了状态保护这就是它能直接拿去改的原因之一。常见做法是直接用云开发把数据库、存储、云函数全交给微信侧。但这套源码没有把所有筹码押在云开发上——它保留了wx.request的直接请求方式通过 config 里的开关决定走本地 Mock 还是真实后端。这样做的好处是前端开发在没有后端接口的情况下也能把页面开发完等后端就绪后只需要改一个配置项。2.2 技术栈与目录设计整体技术栈是原生微信小程序没有引入第三方 UI 框架。为什么这么选因为微信小程序的组件系统本身就提供了 picker、swiper、scroll-view 这类常用组件多数业务页面用原生组件就够。引入第三方框架看着漂亮但要额外处理 npm 构建、组件覆盖、基础库版本兼容对需要快速落地的项目反而是负担。数据层分两层第一层是 Mock 数据放在utils/mock.js里它存在的意义不是骗你是让前端开发不被后端阻塞第二层是真实接口走config.js里的baseUrl请求通过utils/request.js统一发出。这种设计最直观的价值你不需要在每个页面里写一遍wx.request也不需要因为接口地址变了去改几十个文件。目录结构如下小程序根目录 ├── app.js # 全局逻辑启动时读取配置、注入全局对象 ├── app.json # 全局配置页面路由、窗口、tabBar ├── app.wxss # 全局样式变量 ├── utils/ │ ├── config.js # 环境配置mock开关、baseUrl、请求超时 │ ├── request.js # 请求封装统一处理loading、错误、Promise化 │ └── mock.js # Mock数据表以url为key返回模拟数据 ├── pages/ │ ├── index/ # 首页服务列表 │ ├── detail/ # 详情页服务介绍 │ ├── order/ # 预约页表单提交 │ └── mine/ # 我的预约记录 ├── components/ │ └── service-card/ # 可复用服务卡片组件 └── project.config.json # 开发者工具项目配置核心入口要特别说一句app.js很多初学者拿到源码第一件事就是看页面结果在小程序里找「入口函数」找了半天。小程序里没有传统意义上的 main 函数app.js的onLaunch就是入口。它在每个页面初始化之前先执行适合做登录检查、全局环境赋值、缓存预热这些事。2.3 全局配置与页面路由app.json是开发者工具用来理解整个项目的关键它决定了哪些页面会被编译、首页是谁、tabBar 长什么样。这套源码里配置了四个页面pages/index/index在第一项也就是打开小程序第一个进的地方tabBar 的三个 tab 分别是首页、预约、我的。tabBar 的 icon 在真实项目里经常被开发者忽略一旦图片缺失tab 就会在真机上渲染异常这个问题后面避坑章会重点说。project.config.json里有一个容易被忽略的字段是compileType它标记项目类型是miniprogram而不是plugin或game。如果你下载的源码这个字段被改错了开发者工具会直接报「不是有效的小程序项目」。这类问题多数是文件编码或 JSON 多逗号导致的。页面与接口的对应关系也很清晰首页pages/index拉取/services详情页pages/detail拉取/services/{id}预约页pages/order提交/order/create我的页面pages/mine拉取/orders。每个页面只管自己的数据和交互不做跨页面直接调用数据依赖全部走接口层这让全局数据流变得很好追踪。2.4 config.js 里的环境开关设计config.js是整个项目里改动最频繁但逻辑最简单的文件。它长这样// utils/config.js module.exports { mock: true, // true 走 Mockfalse 走真实接口 baseUrl: , // 真实接口的域名前缀如 https://api.example.com timeout: 10000 // 请求超时时间单位 ms }三个参数里mock是二开时最常用到的开关。把它保持为true前端不需要等后端把它改成false所有request调用就会立刻切到wx.request模式。很多人会把timeout忽略但小程序在部分安卓机型上默认请求超时时间较长一旦后端响应慢用户会一直盯着 loading 转圈。显式给一个合理的超时配合 request.js 里的错误捕获体验会好很多。3. 核心代码拆解一次预约请求从点击到渲染的完整链路3.1 app.js全局状态的孵化器我先从全局入口app.js看因为小程序里的页面不是孤立实体它们共享同一个 app 实例。源码里的app.js长这样// app.js const config require(./utils/config) App({ onLaunch() { // 读取缓存中的登录态没有则初始化为空对象 const token wx.getStorageSync(token) || this.globalData.token token this.globalData.mock config.mock }, globalData: { token: , userInfo: null, mock: false } })这段代码的逻辑不复杂但解决了两个问题。一是全局数据在页面之间传递时不再依赖 url 参数比如 order 页面提交成功后想告诉 mine 页面刷新就可以通过getApp().globalData做一个临时的数据桥二是在启动阶段把配置里的 mock 开关复制到全局数据里后续请求封装可以直接从全局读取当前模式不用每次 require。值得注意的一点是wx.getStorageSync(token) || 这个写法是给后面接真实登录态留的口子。如果后端要求用户名密码登录只要把 token 换成登录接口返回的 token 即可页面里所有请求头都会通过 request.js 自动带上。这个设计在二开时会省很多事。3.2 request.js把 wx.request 变成 Promise微信原生的wx.request是回调式的写两个请求还可以接受写多了页面里就会出现「回调地狱」。这套源码用 Promise 做了一个统一封装它还处理了一个容易翻车的点请求成功的 statusCode 并不一定是 200后端偶尔会返回 200 但业务 code 是失败。看看这段代码// utils/request.js const config require(./config) const app getApp() function request(options) { const { url, method GET, data {} } options return new Promise((resolve, reject) { if (config.mock) { // Mock 模式从 mock.js 中按 url 匹配数据 const mockData require(./mock)[url] if (mockData) { setTimeout(() resolve({ statusCode: 200, data: mockData }), 200) } else { reject(new Error(Mock 数据未定义${url})) } return } wx.request({ url: config.baseUrl url, method, data, header: { Content-Type: application/json, Authorization: app.globalData.token ? Bearer ${app.globalData.token} : }, success(res) { if (res.statusCode 200 res.data.code 0) { resolve(res.data) } else { reject(new Error(res.data.message || 请求异常${res.statusCode})) } }, fail(err) { reject(err) } }) }) } module.exports request这段代码里有几个参数值得说说。method默认是GET但调用时可以覆盖为POSTdata默认给空对象避免传 undefined 导致某些低版本基础库报错url直接用的是/services这样的简写路径真实请求时前面会拼接config.baseUrl而 Mock 模式下这个 url 刚好是mock.js的键名一个 url 两处复用逻辑上很顺。很多人在封装 request 时会忽略res.data.code的判断。如果后端返回结构是{ code: 0, data: [], message: }前端只判断了 HTTP 状态码就会在页面里拿到一个有壳没肉的响应对象等做到错误提示时才发现后端给的提示词根本没透传过来。这套源码在success里做了双层判断HTTP 和业务码都过一遍错误信息直接由 reject 带出页面 catch 里统一展示。3.3 首页列表从 onLoad 到 setData 的数据流首页是pages/index/index.js它做的事可以拆成三步加载时请求数据、请求期间控制 loading、请求完成后把数据渲染到视图。看核心代码// pages/index/index.js const request require(../../utils/request) Page({ data: { serviceList: [], loading: false }, onLoad() { this.fetchServiceList() }, fetchServiceList() { this.setData({ loading: true }) return request({ url: /services }) .then(res { this.setData({ serviceList: res.data || [], loading: false }) }) .catch(err { this.setData({ loading: false }) wx.showToast({ title: err.message || 加载失败, icon: none }) }) }, onPullDownRefresh() { return this.fetchServiceList().then(() wx.stopPullDownRefresh()) } })这里有一个细节值得单独讲fetchServiceList返回的是request(...)这个 Promise这样onPullDownRefresh里就可以直接return它再在.then里调用wx.stopPullDownRefresh。如果不这样写wx.stopPullDownRefresh会在数据回来之前就执行下拉动画提前停掉观感很怪。setData是页面数据和视图连接的关键。微信的机制是setData会把数据从逻辑层传输到渲染层所以每次调用都有开销。这里在serviceList加载完成后一次性更新避免在循环里多次 setData 造成页面卡顿。如果你看到某些源码在for循环里频繁 setData那基本是某个即时聊天或者动画场景普通列表页这么做性能一定打折扣。3.4 表单提交校验、loading 与回调时序预约表单在pages/order/order.js它需要处理的不止是提交一个 request。看这段// pages/order/order.js const request require(../../utils/request) Page({ data: { submitting: false, form: {} }, handleFieldChange(e) { const field e.currentTarget.dataset.field this.setData({ [form.${field}]: e.detail.value }) }, submitOrder() { const { form, submitting } this.data if (submitting) return if (!this.validateForm(form)) return this.setData({ submitting: true }) request({ url: /order/create, method: POST, data: form }) .then(() { wx.showToast({ title: 预约成功, icon: success }) setTimeout(() wx.navigateBack(), 1500) }) .catch(err { wx.showToast({ title: err.message || 提交失败, icon: none }) }) .finally(() { this.setData({ submitting: false }) }) } })注意submitting这个字段。它本质是一个「防重复提交」的锁用户点击提交后马上置为 true在请求结束前再点击会直接 return等接口结果回来后再解开。很多线上事故就是缺了这一步用户手一抖点了两次后端收到两笔相同订单。handleFieldChange里用的e.currentTarget.dataset.field是从 wxml 上的>// utils/config.js module.exports { mock: false, baseUrl: https://your-domain.example.com/api, timeout: 10000 }第二步确认utils/request.js里success分支的业务码判断和后端返回一致。比如后端返回{ code: 200, data: [...], message: ok }那么request.js里的res.data.code 0就要改成res.data.code 200。这一步是二开时最容易漏的漏了不会报错只是永远进入 reject 分支页面一直弹「请求异常」。第三步回到页面测试首页request({ url: /services })会被拼成https://your-domain.example.com/api/services如果后端接口里不带/api前缀就把baseUrl的/api去掉。这种配置上的小差异靠代码审查很难发现跑一次console.log(config.baseUrl url)是最快的验证方式。加新页面也是同样的套路在app.json的pages数组里加一行路径然后在对应目录下创建四个文件。页面之间跳转用wx.navigateTotab 页切换用wx.switchTab这套源码里已经踩完了这些坑按它的既有模式复制页面是最不容易出错的。从那以后我每次做二开都会把「先跑通一个接口再动页面」当成铁律。不管拿到的是什么源码我都会先在控制台里手动调一次request确认封装层没有吞掉错误再去改页面上的数据流。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑