certificate-photo 状态管理三件套:globalData、pageData与eventChannel如何协作?
certificate-photo 状态管理三件套:globalData、pageData与eventChannel如何协作?
【免费下载链接】certificate-photo一个生成证件照的小程序,微信云原生开发小程序。 只fork不star是很没品的。项目地址: https://gitcode.com/gh_mirrors/ce/certificate-photo
在微信小程序开发中,证件照小程序状态管理一直是新手最头疼的环节:页面之间传参、全局共享数据、非响应式缓存,到底该用哪一招?今天我们就以开源证件照小程序certificate-photo为例,拆解它最核心的状态管理三件套——globalData、pageData与eventChannel,看看一个完整的证件照生成流程(选尺寸 → 上传照片 → 智能抠图 → 换背景 → 保存)是如何在三个组件之间无缝协作的。读完你会发现:掌握这三件套,就等于拿到了微信小程序状态管理的入门钥匙 🔑。
为什么小程序需要三套状态管理方案?
很多新手喜欢"一招鲜":要么把所有数据塞进globalData,要么全用setData渲染。certificate-photo 的答案是:按数据的生命周期和用途分而治之,这才是微信小程序状态管理的精髓。
| 方案 | 生命周期 | 典型用途 | 是否触发渲染 |
|---|---|---|---|
| globalData | 整个小程序 | 用户身份、全局配置 | 否 |
| pageData | 单个页面 | 图片处理中间数据 | 否 |
| eventChannel | 一次页面跳转 | 父子页面传递参数 | 否 |
| data + setData | 页面渲染 | 绑定到 WXML 的数据 | 是 |
注意表格最后一行:只有data 中的字段才是响应式,其余三件套本质上都是"旁路缓存",专门用来存放不需要渲染的数据,从而避免频繁setData带来的性能损耗。
globalData:全小程序共享的"公共储物柜"
globalData是 App 实例上的全局对象,整个小程序生命周期内所有页面都能通过getApp().globalData访问。在 certificate-photo 的 app.js 中,它承担了两类任务:
任务一:存放全局配置数据。比如 15 种证件照规格的photoSizeList(一寸、二寸、小二寸、结婚证……),首页 index.js 和选照片页 preEdit.js 都直接引用它:
const app = getApp() data: { photoSizeList: app.globalData.photoSizeList }任务二:异步写入用户身份。小程序启动时通过云函数addUser获取用户openid,成功后再写入globalData.openid。后续编辑页要查询用户剩余次数时,直接读取即可。⚠️ 这里有个新手常踩的坑:openid是异步获取的,页面onLoad时可能还没赋值,所以读取前务必做空值判断。
最佳实践提示:globalData 只放"全局共享 + 变化不频繁"的数据,千万别把页面级中间数据堆进来,否则会导致内存泄漏和状态混乱。
pageData:不渲染的"页面工作台"
如果你细心观察,会发现 certificate-photo 的页面里藏着两个模块级的pageData常量:
- 选照片页 preEdit.js:存放原始图片路径、压缩图路径、目标宽高等;
- 编辑页 editPhotoPlus.js:存放抠图所需的原图地址、图片类型、压缩地址。
这些数据为什么不放进data?因为WXML 根本不需要它们!放进 data 只会白白触发视图更新。以编辑页为例,百度抠图、VIP 精细抠图都用pageData.originImgPath等字段,全程零渲染开销,配合Object.assign更新,代码清晰又高效 💡。
记忆口诀:data 负责"给人看",pageData 负责"给代码用"。
eventChannel:页面跳转的"专属快递通道"
当从选照片页跳转到编辑页时,要传递抠图结果、图片宽高等一整套数据,如果全拼在 URL 里不仅冗长还有长度限制。certificate-photo 的做法是使用eventChannel(事件通道),这是wx.navigateTo自带的页面间通信机制。
发送端(preEdit.js):
wx.navigateTo({ url: '/pages/editPhoto/editPhotoPlus/editPhotoPlus', success(res) { res.eventChannel.emit('acceptDataFromOpenerPage', {...data, width, height}) } })接收端(editPhotoPlus.js):
const eventChannel = this.getOpenerEventChannel() eventChannel.on('acceptDataFromOpenerPage', (data) => { ... })更妙的是,eventChannel 还支持"反向通信":编辑页打开换装/换发型子页面时,在wx.navigateTo里注册events监听,子页面通过eventChannel.emit('selectClothes', {imgUrl})把选中的素材回传,父页面setData更新视图——整个过程干净利落,无需任何全局变量 👏。
三件套如何串联一条完整链路?
让我们把整个证件照生成流程串起来,看它们如何各司其职:
- 首页读取
globalData.photoSizeList展示尺寸列表; - 用户选完尺寸,跳转选照片页,尺寸数据经 URL 传入,处理过程中的图片数据暂存于
pageData; - 抠图完成后,通过
eventChannel.emit把原图、压缩图、宽高一次性"快递"给编辑页; - 编辑页把结果存入自己的
pageData,同时用globalData.openid查询剩余次数,换装换发型时再用eventChannel与子页面双向通信; - 最终合成图片,跳转完成页。
全程下来,globalData 管全局、pageData 管页面、eventChannel 管跳转,各管一段,互不干扰,这就是 certificate-photo 状态管理三件套协作的全部秘密。
新手避坑清单:三件套常见误区
- ❌把 pageData 里的数据直接绑定 WXML→ 改值不刷新,画面不动;
- ❌全局数据都用 globalData→ 页面多了以后难以追踪来源;
- ❌在 eventChannel 的 emit 中传太复杂的大对象→ 建议只传关键字段;
- ✅区分"需要渲染"和"仅需计算",前者进 data,后者进 pageData,这是最值得养成的习惯。
小结:三件套的本质是"按需分层"
certificate-photo 的实践告诉我们:微信小程序状态管理没有银弹,只有合适的场景用合适的工具。globalData提供全局视野,pageData专注单页计算,eventChannel打通页面链路,三者配合起来,才能写出既高效又易维护的证件照小程序。下次你写自己的小程序时,不妨也先画一张"数据流向图",再决定每份数据该交给谁 👍。
如果你想运行这个项目,可以 clone 仓库https://gitcode.com/gh_mirrors/ce/certificate-photo,打开miniprogram目录,用微信开发者工具导入即可体验这套完整的状态管理实践。
【免费下载链接】certificate-photo一个生成证件照的小程序,微信云原生开发小程序。 只fork不star是很没品的。项目地址: https://gitcode.com/gh_mirrors/ce/certificate-photo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
