本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、页面生命周期(Page
)
适用于 @Entry
装饰的页面组件,按执行顺序排列:
方法 | 触发时机 | 典型用途 |
---|---|---|
onPageShow | 页面每次显示时(首次进入或从后台返回) | 恢复动画、刷新数据 |
onPageHide | 页面隐藏时(跳转到其他页面或进入后台) | 暂停耗电操作(如GPS、动画) |
onBackPress | 用户点击返回按钮时 | 拦截返回操作(如提示保存未提交表单) |
aboutToAppear | 页面即将显示前(比onPageShow 更早,仅触发一次) | 初始化页面数据 |
aboutToDisappear | 页面即将销毁前(比onPageHide 更早) | 释放资源(如取消网络请求) |
示例代码:
@Entry
@Component
struct MyPage {
aboutToAppear() {
console.log('页面即将加载')
}
onPageShow() {
console.log('页面已显示')
}
onBackPress() {
// 返回true表示拦截返回键
return false
}
}
二、组件生命周期(Component
)
适用于普通 @Component
或 @ComponentV2
装饰的组件:
方法 | 触发时机 | 与页面的区别 |
---|---|---|
aboutToAppear | 组件首次创建或从组件树重新挂载时 | 页面级方法优先于组件执行 |
aboutToDisappear | 组件即将从组件树移除时 | 先于页面aboutToDisappear 执行 |
onPageShow | 所在页面显示时(需组件在当前页面中) | 与页面方法同步触发 |
onPageHide | 所在页面隐藏时 | 与页面方法同步触发 |
示例代码:
@Component
struct MyComponent {
aboutToAppear() {
console.log('组件即将显示')
}
aboutToDisappear() {
console.log('组件即将销毁')
}
}
三、UIAbility 生命周期
UIAbility 是鸿蒙应用的核心进程单元,负责管理应用窗口和全局状态。其生命周期方法如下:
方法 | 触发时机 | 典型用途 |
---|---|---|
onCreate | Ability 首次创建时(冷启动或完全销毁后重新创建) | 初始化全局数据、申请权限 |
onWindowStageCreate | 窗口舞台(WindowStage)创建完成(此时可加载页面) | 设置根页面 windowStage.loadContent() |
onForeground | Ability 从后台回到前台(包括首次启动) | 恢复业务逻辑(如订阅事件) |
onBackground | Ability 进入后台(仍驻留内存) | 暂停高耗电操作(如动画、GPS) |
onWindowStageDestroy | 窗口舞台销毁(如关闭分屏窗口或主动销毁) | 释放窗口相关资源 |
onDestroy | Ability 完全销毁前(内存不足或主动退出) | 释放所有应用资源 |
示例代码:
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
console.log('Ability 创建')
}
onWindowStageCreate(windowStage: window.WindowStage) {
windowStage.loadContent('pages/Index', (err) => {
if (err) console.error('加载页面失败')
})
}
onForeground() {
console.log('Ability 回到前台')
}
}
二、六大典型交互场景的生命周期顺序
1. 首次启动应用
关键点:
-
WindowStage的桥梁作用
onWindowStageCreate
完成后才会加载页面内容(loadContent
)- 窗口舞台(WindowStage)是页面和Ability的中间层
-
页面与组件的初始化分离
aboutToAppear
仅完成节点挂载,此时尚未渲染onPageShow
时才完成首次渲染。
2. 跳转到新页面(A → B)
关键点:
-
子组件销毁时机
- 原页面的子组件
aboutToDisappear
早于新页面初始化(确保资源释放不会阻塞新页面创建)
- 原页面的子组件
-
页面隐藏与显示的顺序
- 原页面
onPageHide
触发后,必须等待其子组件销毁完成,才会初始化新页面。
- 原页面
3. 返回上一个页面(B → A)
行为:
- 返回
true
时:系统不执行页面退出,由开发者控制后续流程 - 返回
false
时:继续默认返回逻辑
4. 按Home键进入后台
关键点:
-
页面与Ability的优先级
- 页面级生命周期(
onPageHide
)优先于 UIAbility的onBackground
触发 - 系统会先暂停UI渲染,再挂起应用进程
- 页面级生命周期(
-
子组件处理逻辑
- 若子组件监听了
onPageHide
(如通过事件订阅),则与父页面同步触发 - 不会触发
aboutToDisappear
(页面仍驻留内存)。
- 若子组件监听了
5. 从后台返回应用
关键点:
-
UIAbility优先恢复
- 系统会先激活Ability进程,再恢复页面渲染
- 此时页面尚未显示,但已可执行数据预加载
-
页面与子组件的关系
- 父页面的
onPageShow
触发后,才会通知子组件 - 子组件无需单独监听Ability状态
- 父页面的
6. 关闭最后一个页面(退出应用)
关键点:
- 子组件优先销毁
- 子组件的
aboutToDisappear
早于 父页面触发(遵循从叶子节点到根节点的销毁顺序)
- 子组件的
- UIAbility 的阶段性销毁
- 先销毁窗口资源(
onWindowStageDestroy
),再完全销毁Ability(onDestroy
)
- 先销毁窗口资源(
三、关键交互规则总结
场景 | 是否触发 onPageHide | 是否触发 aboutToDisappear | 关键区别 |
---|---|---|---|
跳转新页面 | ✅ 是 | ❌ 否 | 原页面被覆盖但仍驻留内存 |
返回上一个页面 | ❌ 否 | ✅ 是 | 原页面被销毁 |
进入后台 | ✅ 是 | ❌ 否 | Ability可能继续存活 |
分屏窗口关闭 | ❌ 否 | ✅ 是 | 仅销毁当前窗口 |
-
设计逻辑差异:
onPageHide
用于处理 页面被覆盖但仍驻留内存 的场景(如跳转新页面)。aboutToDisappear
表示 页面即将被销毁(返回操作会移除当前页)。router.back()
会模拟返回键行为,但直接调用时不触发onBackPress()
。- 若应用配置了
backgroundMode
,返回桌面后UIAbility可能仅进入onBackground
而不销毁。
四、使用示例
1. 数据初始化与资源释放
aboutToAppear() {
// 初始化页面数据(每次显示都会调用)
this.loadData()
}
aboutToDisappear() {
// 释放独占资源(如相机、传感器)
camera.release()
}
2. 返回键拦截与数据保存
onBackPress() {
if (this.isFormDirty) {
showDialog('是否保存修改?', () => {
this.saveData()
router.back() // 手动触发返回
})
return true // 拦截默认返回
}
return false
}
3. 多页面状态同步
// 使用AppStorage共享全局状态
onPageHide() {
AppStorage.SetOrCreate('tempData', this.formData)
}
// 下一个页面读取
aboutToAppear() {
this.formData = AppStorage.Get('tempData')
}
五、特殊场景处理
1. 分屏模式
- 每个窗口独立触发生命周期
- 关闭分屏窗口时:
aboutToDisappear
→onWindowStageDestroy
(仅当前窗口)
2. 异步操作风险
aboutToDisappear() {
// ❌ 错误:异步操作可能无法完成
saveToDatabase(data, () => console.log('保存成功'))
// ✅ 正确:同步保存
AppStorage.SetOrCreate('cache', data)
}