简介
本技术文档围绕 DouPHP 小程序的“页面生命周期管理”展开,系统阐述页面从创建到销毁的完整生命周期(onLoad、onShow、onReady、onHide、onUnload),并结合仓库中的实际代码,说明:
- 页面初始化流程与数据加载策略
- 资源清理机制与内存泄漏防护
- 页面级状态、组件状态与全局状态的协调管理
- 最佳实践与性能优化建议
- 错误处理策略与常见问题定位
项目结构
DouPHP 的小程序实现位于 miniprogram 目录下,包含 default 与 company 两套主题/业务模板。每个模板均提供:
- 应用入口 app.ts:负责全局初始化、错误捕获、自动更新、推广参数解析等
- 状态管理 stores:基于 MobX 的全局状态聚合与引导
- 页面 pages:以功能模块划分,每个页面拥有独立的 TypeScript 逻辑文件
- 类型定义 libs/miniprogram-api-typings:提供微信小程序 API 的类型声明,包括页面生命周期接口
graph TB
subgraph "小程序应用"
A["应用入口<br/>app.ts"]
B["状态引导<br/>stores/index.ts"]
C["认证状态<br/>stores/auth.ts"]
end
subgraph "首页示例"
D["页面逻辑<br/>pages/index/index.ts"]
end
A --> B
B --> C
A --> D
B --> D
核心组件
- 应用入口(App)
- onLaunch:注册 HTTP 错误拦截器、解析推广参数、引导全局 store、计算导航栏高度、启动自动更新、调试模式开关
- onShow:再次尝试解析推广参数(适用于后台切回或卡片冷启)
- onError/onUnhandledRejection/onPageNotFound:全局异常与路由缺失的统一处理
- 状态引导(bootstrapStores)
- 先 hydrate(从 storage 恢复本地状态,实现秒开)
- 再 refresh/restore(网络刷新;失败保留本地缓存)
- 绑定购物车角标(统一由 cartStore.badge 驱动)
- 认证状态(authStore)
- hydrate:从 storage 恢复登录态
- restore:拉取用户信息并设置 is_login/is_vip/is_work/is_distribution
- ensureLogin:未登录时跳转登录页
- login/logout:持久化凭证与状态重置
- 页面示例(首页 index)
- onLoad:设置标题、显示分享菜单、绑定 store、请求首页数据、加载商品列表
- onShow:刷新购物车状态
- onReady:恢复认证态后根据工作态跳转
- onUnload:解绑 store 绑定,释放资源
架构总览
下图展示了小程序应用启动到页面渲染的关键调用链与数据流:
sequenceDiagram
participant WX as "微信宿主"
participant App as "应用入口(app.ts)"
participant Store as "状态引导(stores/index.ts)"
participant Auth as "认证状态(stores/auth.ts)"
participant Page as "页面(index.ts)"
WX->>App : 触发 onLaunch(options)
App->>App : 注册HTTP错误拦截器
App->>App : 解析推广参数(user_sn)
App->>Store : bootstrapStores()
Store->>Auth : hydrate() / restore()
Store-->>App : 完成状态预热
App->>WX : 计算导航栏高度/启动自动更新
WX->>Page : 页面 onLoad(query)
Page->>Store : 绑定 store 字段
Page->>Page : 发起网络请求(首页数据/商品列表)
WX->>Page : 页面 onReady()
Page->>Auth : restore() -> 可能跳转工作页
WX->>Page : 页面 onShow()
Page->>Store : 刷新购物车状态
WX->>Page : 页面 onHide()/onUnload()
Page->>Page : 解绑 store 绑定/清理资源
详细组件分析
页面生命周期钩子与执行时机
- onLoad(query)
- 页面加载时触发一次,适合读取路由参数、初始化数据、发起首屏请求
- 在首页中用于设置标题、绑定 store、请求首页数据与商品列表
- onShow()
- 页面显示/切入前台时触发,适合刷新需要实时性的数据(如购物车数量)
- onReady()
- 页面初次渲染完成,适合进行视图交互与 DOM 查询(如滚动条宽度测量)
- 在首页中用于恢复认证态并根据工作态跳转
- onHide()
- 页面隐藏/切入后台时触发,适合暂停定时器、取消监听
- onUnload()
- 页面卸载时触发,适合释放资源(如解绑 store 绑定、清理事件监听)
页面初始化流程与数据加载策略
- 应用层
- onLaunch:注册 HTTP 错误拦截器、解析推广参数、引导全局 store、计算导航栏高度、启动自动更新、开启调试模式
- 状态层
- bootstrapStores:先 hydrate(storage 秒开),再 refresh/restore(网络刷新),最后绑定购物车角标
- 页面层
- onLoad:绑定 store 字段、请求首页数据、加载商品列表
- onReady:恢复认证态,必要时跳转工作页
- onShow:刷新购物车状态
flowchart TD
Start(["应用启动"]) --> Launch["App.onLaunch"]
Launch --> Bootstrap["bootstrapStores()"]
Bootstrap --> Hydrate["hydrate() 从 storage 恢复"]
Hydrate --> Refresh["refresh()/restore() 网络刷新"]
Refresh --> BindBadge["绑定购物车角标"]
BindBadge --> PageLoad["页面 onLoad()"]
PageLoad --> FetchData["请求首页数据/商品列表"]
FetchData --> Ready["页面 onReady()"]
Ready --> AuthRestore["恢复认证态/可能跳转"]
AuthRestore --> Show["页面 onShow()"]
Show --> End(["页面就绪并可交互"])
资源清理机制与内存泄漏防护
- 页面卸载时解绑 store 绑定,避免引用残留导致内存泄漏
- 使用 wx.nextTick 与 SelectorQuery 获取节点尺寸后,仅保存必要计算值,避免持有大对象
- 对网络请求的错误分支进行兜底,确保 UI 状态可恢复(如 loadpage 置为 false)
页面状态管理(页面级、组件级、全局状态)
- 全局状态(stores)
- commonStore:站点信息、语言、特性开关、导航列表等
- authStore:登录态、VIP/工作/分销标志
- cartStore:购物车数据与角标
- 页面级状态(Page.data)
- 首页维护分类指示器、商品列表、分页、加载状态等
- 组件级状态(未在本文直接展示)
- 通过组件 lifetimes 与 data 管理局部状态
classDiagram
class CommonStore {
+site
+lang
+data
+param
+features
+nav_list
+hydrate()
+refresh()
}
class AuthStore {
+api_token
+user_id
+loginEd
+is_login
+is_vip
+is_work
+is_distribution
+hydrate()
+restore()
+ensureLogin()
+login()
+logout()
}
class CartStore {
+badge
+refresh()
}
class IndexPage {
+navigationBarAndStatusBarHeight
+index
+product_list
+page
+nomore
+loadpage
+onLoad()
+onShow()
+onReady()
+onUnload()
}
IndexPage --> CommonStore : "绑定字段"
IndexPage --> AuthStore : "恢复认证态"
IndexPage --> CartStore : "刷新购物车"
典型场景的生命周期使用方法
- 首次进入首页
- onLoad:设置标题、绑定 store、请求首页数据与商品列表
- onReady:恢复认证态,若处于工作状态则跳转到工作页
- 切换到前台
- onShow:刷新购物车状态,保证角标与数量一致
- 离开页面
- onUnload:解绑 store 绑定,释放资源
依赖关系分析
- 应用入口依赖状态引导与 HTTP 服务
- 状态引导依赖各 store(common/auth/cart)
- 页面依赖 store 与 HTTP 服务,并在生命周期中触发数据刷新与状态同步
graph LR
App["应用入口(app.ts)"] --> Stores["状态引导(stores/index.ts)"]
Stores --> Auth["认证状态(stores/auth.ts)"]
App --> Page["页面(index.ts)"]
Stores --> Page
Page --> HTTP["HTTP服务"]
性能考量
- 首屏秒开:通过 hydrate 从 storage 恢复状态,减少白屏时间
- 网络刷新:在 hydrate 之后再进行 refresh/restore,失败不影响本地展示
- 角标统一驱动:cartStore.badge 通过 autorun 绑定,避免多处重复 setTabBarBadge
- 延迟加载与分页:商品列表采用分页与触底追加,降低首屏数据量
- 调试模式:非正式版开启 vConsole,便于快速定位问题
故障排查指南
- 全局错误捕获
- App.onError:记录错误日志,调试期弹出 modal
- App.onUnhandledRejection:记录未处理的 Promise 拒绝
- App.onPageNotFound:记录路由不存在的路径,调试期提示
- 认证态异常
- UNAUTHORIZED:统一登出并清空登录态
- 其他错误(NETWORK_ERROR/HTTP_5xx/NOT_FOUND):保留当前登录态,避免弱网导致的假登出
- 页面级错误
- 网络请求失败:显示错误消息,确保 UI 状态可恢复(如 loadpage 置为 false)
结论
DouPHP 小程序通过应用入口、状态引导与页面生命周期的协同,实现了高效、稳定的页面生命周期管理:
- 应用层负责全局初始化与错误处理
- 状态层通过 hydrate/refresh/restore 保障首屏体验与数据一致性
- 页面层在合适的生命周期钩子中进行数据加载、状态刷新与资源清理 结合分页加载、统一角标驱动与调试模式,整体具备良好的性能与可维护性。
附录
- 页面生命周期接口参考
- ILifetime:onLoad、onShow、onReady、onHide、onUnload、onRouteDone、onPullDownRefresh、onReachBottom 等
- 推荐实践清单
- 在 onLoad 中初始化数据与绑定 store
- 在 onShow 中刷新需要实时性的数据
- 在 onReady 中进行视图交互与 DOM 查询
- 在 onHide 中暂停定时器与取消监听
- 在 onUnload 中解绑 store 与释放资源
- 使用 hydrate/refresh/restore 保障首屏与数据一致性
- 统一错误处理与调试模式