Uniapp 生命周期详解:页面生命周期 vs 应用生命周期(附实战示例)
Uniapp 是一个基于 Vue.js 的跨平台开发框架,生命周期管理是其核心机制之一。它分为应用生命周期(整个 App 的全局钩子)和页面生命周期(单个页面的局部钩子)。理解这些钩子的执行顺序和用途,能帮助开发者优化性能、处理数据加载和状态管理。下面我将逐步详解两者的区别、钩子函数,并提供实战示例。
1. 应用生命周期
应用生命周期钩子定义在根组件 App.vue
中,作用于整个应用程序。它们在 App 启动、切换前后台时触发。常用钩子包括:
onLaunch
:App 首次启动时触发,用于初始化全局数据(如登录状态)。onShow
:App 从后台切换到前台时触发(如用户返回 App)。onHide
:App 从前台切换到后台时触发(如用户切换到其他 App)。onError
:App 发生脚本错误时触发,用于错误监控。
特点:
- 全局性:影响整个 App。
- 执行顺序:
onLaunch
→onShow
(首次启动)→ 后续onShow
/onHide
(切换前后台)。 - 用途:处理 App 级事件,如全局配置、错误日志。
2. 页面生命周期
页面生命周期钩子定义在单个页面组件(如 pages/index/index.vue
)中,作用于特定页面。它们在页面加载、显示、隐藏或卸载时触发。常用钩子包括:
onLoad
:页面加载时触发,用于获取路由参数(如options
)。onShow
:页面显示时触发(如页面进入前台)。onReady
:页面首次渲染完成时触发,用于操作 DOM。onHide
:页面隐藏时触发(如页面跳转或切换到后台)。onUnload
:页面卸载时触发(如页面被关闭),用于清理资源(如定时器)。onPullDownRefresh
:下拉刷新时触发。onReachBottom
:页面滚动到底部时触发(用于上拉加载更多)。
特点:
- 局部性:只影响当前页面。
- 执行顺序:
onLoad
→onShow
→onReady
→ 后续onShow
/onHide
→onUnload
。 - 用途:处理页面级事件,如数据请求、UI 交互。
3. 页面生命周期 vs 应用生命周期:关键区别
下表总结两者的核心差异:
特性 | 应用生命周期 | 页面生命周期 |
---|---|---|
作用范围 | 全局(整个 App) | 局部(单个页面) |
定义位置 | App.vue 文件 | 页面组件(如 pages/xxx.vue ) |
主要钩子 | onLaunch , onShow , onHide | onLoad , onShow , onReady , onUnload |
触发时机 | App 启动/切换前后台 | 页面加载/显示/隐藏/卸载 |
典型用途 | 全局初始化、错误处理 | 页面数据加载、DOM 操作 |
执行顺序示例 | App 启动:onLaunch → onShow | 页面打开:onLoad → onShow → onReady |
核心区别:
- 应用生命周期优先于页面生命周期。例如,App 启动时,先执行
App.vue
的onLaunch
,再执行页面的onLoad
。 - 页面切换时:当新页面打开,旧页面的
onHide
触发;新页面的onLoad
触发。 - App 切换前后台时:所有页面的
onHide
/onShow
可能触发,但应用钩子onHide
/onShow
优先。
4. 实战示例:登录状态管理
下面是一个完整示例,展示如何结合应用和页面生命周期实现登录状态检查。场景:App 启动时检查全局登录状态,首页加载时显示用户信息。
文件结构:
App.vue
:定义应用生命周期,处理全局登录。pages/index/index.vue
:定义页面生命周期,显示用户数据。
代码实现:
步骤 1: App.vue(应用生命周期)
// App.vue
export default {// 应用生命周期钩子onLaunch(options) {// App 启动时检查登录状态(模拟全局数据)console.log('App launched, options:', options);this.globalData.isLoggedIn = false; // 初始未登录this.checkLogin(); // 调用登录检查方法},onShow() {console.log('App shown'); // App 切换到前台时触发},onHide() {console.log('App hidden'); // App 切换到后台时触发},methods: {checkLogin() {// 模拟登录检查(如调用 API)setTimeout(() => {this.globalData.isLoggedIn = true; // 假设登录成功console.log('Login status updated');}, 1000);}},globalData: {isLoggedIn: false // 全局共享数据}
}
步骤 2: pages/index/index.vue(页面生命周期)
// pages/index/index.vue
export default {data() {return {userInfo: null // 页面级数据};},// 页面生命周期钩子onLoad(options) {console.log('Page loaded, options:', options); // 获取路由参数this.loadUserData(); // 加载用户数据},onShow() {console.log('Page shown'); // 页面显示时触发},onReady() {console.log('Page ready'); // 页面渲染完成,可操作 DOM},onUnload() {console.log('Page unloaded'); // 页面关闭时清理},methods: {loadUserData() {// 从全局数据获取登录状态const app = getApp();if (app.globalData.isLoggedIn) {this.userInfo = { name: 'User1', age: 25 }; // 模拟数据console.log('User data loaded');} else {console.log('User not logged in');}}}
}
步骤 3: 运行流程说明
- App 启动:
- 执行
App.vue
的onLaunch
:初始化globalData.isLoggedIn = false
,开始检查登录。 - 然后
onShow
触发。
- 执行
- 首页加载:
- 执行
index.vue
的onLoad
:调用loadUserData
方法。 - 由于登录检查是异步的,
userInfo
初始为null
。 - 稍后,
App.vue
的checkLogin
完成,设置globalData.isLoggedIn = true
。
- 执行
- 页面显示:
onShow
和onReady
触发,页面渲染完成。- 如果需要更新数据,可以在
onShow
中重新检查全局状态。
- App 切换后台:
- 触发
App.vue
的onHide
,然后所有页面的onHide
。
- 触发
- 页面关闭:
- 触发
onUnload
,清理资源。
- 触发
控制台输出示例:
App launched, options: {path: 'pages/index/index'}
App shown
Page loaded, options: {}
Page shown
Page ready
Login status updated // 来自 App.vue 的异步更新
实际效果:首页会显示用户信息(如果登录成功)。这演示了如何通过应用钩子管理全局状态,页面钩子处理局部逻辑。
5. 最佳实践与常见问题
- 最佳实践:
- 在
onLaunch
中初始化全局数据(如 token)。 - 在
onLoad
中获取页面参数(如options.id
)。 - 在
onReady
中操作 DOM(如使用uni.createSelectorQuery
)。 - 在
onUnload
中清理定时器或事件监听器,避免内存泄漏。
- 在
- 常见问题:
- 钩子不触发:确保钩子正确定义在
export default
中。 - 执行顺序混乱:应用钩子总是优先;页面切换时,旧页面
onHide
先于新页面onLoad
。 - 数据不同步:使用
getApp()
访问全局数据,或在onShow
中刷新页面状态。
- 钩子不触发:确保钩子正确定义在