本文献给:
已掌握状态管理基础、能独立完成组件间数据通信的鸿蒙开发者。本文将系统讲解 HarmonyOS 中页面生命周期与组件生命周期的各个钩子函数,涵盖触发时机、执行顺序以及新旧版本组件生命周期的差异对比,帮助你精确掌控应用运行的关键节点。
你将学到:
- 页面生命周期钩子(onPageShow、onPageHide、onBackPress)的触发时机与应用
- 组件经典生命周期(aboutToAppear、aboutToDisappear)的调用时机
- 新版组件生命周期新增钩子的作用
- 新旧版本组件生命周期的对比与选型建议
- 通过日志实验追踪生命周期执行顺序
- 各钩子函数的适用场景与常见错误
目录
- 一、页面生命周期
-
- [1.1 onPageShow ------ 页面显示时触发](#1.1 onPageShow —— 页面显示时触发)
- [1.2 onPageHide ------ 页面隐藏时触发](#1.2 onPageHide —— 页面隐藏时触发)
- [1.3 onBackPress ------ 返回键按下时触发](#1.3 onBackPress —— 返回键按下时触发)
- [1.4 页面生命周期执行顺序](#1.4 页面生命周期执行顺序)
- 二、组件经典生命周期
-
- [2.1 aboutToAppear ------ 组件即将出现](#2.1 aboutToAppear —— 组件即将出现)
- [2.2 aboutToDisappear ------ 组件即将销毁](#2.2 aboutToDisappear —— 组件即将销毁)
- [2.3 经典生命周期执行顺序示例](#2.3 经典生命周期执行顺序示例)
- 三、新版组件生命周期
-
- [3.1 onDidBuild ------ build 执行完成后触发](#3.1 onDidBuild —— build 执行完成后触发)
- [3.2 aboutToReuse ------ 组件复用时触发](#3.2 aboutToReuse —— 组件复用时触发)
- [3.3 onWillApplyTheme ------ 主题变化前触发](#3.3 onWillApplyTheme —— 主题变化前触发)
- 四、新旧生命周期对比
-
- [4.1 触发顺序对比](#4.1 触发顺序对比)
- [4.2 新旧版本关键差异](#4.2 新旧版本关键差异)
- [4.3 选型建议](#4.3 选型建议)
- 五、生命周期实验与记忆方法
-
- [5.1 日志实验法](#5.1 日志实验法)
- [5.2 关键触发条件速查表](#5.2 关键触发条件速查表)
- 六、常见错误与注意事项
-
- [6.1 在 aboutToAppear 中执行耗时操作](#6.1 在 aboutToAppear 中执行耗时操作)
- [6.2 忘记在 aboutToDisappear 中释放资源](#6.2 忘记在 aboutToDisappear 中释放资源)
- [6.3 混淆页面生命周期与组件生命周期](#6.3 混淆页面生命周期与组件生命周期)
- [6.4 在 build 方法中执行副作用](#6.4 在 build 方法中执行副作用)
- [6.5 onBackPress 使用不当导致无法退出](#6.5 onBackPress 使用不当导致无法退出)
- [6.6 复用组件的状态残留](#6.6 复用组件的状态残留)
- 七、小结
一、页面生命周期
页面生命周期是指一个页面从进入前台到离开前台所经历的一系列回调事件。在 HarmonyOS 中,页面由 @Entry 装饰的组件承载,其生命周期钩子定义在该组件内部。
1.1 onPageShow ------ 页面显示时触发
当页面进入前台、变为可见状态时调用。每次页面显示都会触发,包括从其他页面返回、从后台切回前台等场景。
typescript
@Entry
@Component
struct MyPage {
@State message: string = '页面未显示';
onPageShow() {
this.message = '页面已显示';
console.log('onPageShow: 页面进入前台');
}
build() {
Column() {
Text(this.message).fontSize(20)
}
}
}
触发时机:
- 页面首次加载完成并显示时。
- 从其他页面返回当前页面时。
- 应用从后台切回前台,且当前页面在最顶层时。
适用场景:
- 页面可见时刷新数据(如从网络重新拉取)。
- 恢复定时器或动画。
- 重新检查权限、登录状态等。
1.2 onPageHide ------ 页面隐藏时触发
当页面离开前台、变为不可见状态时调用。通常发生在跳转到其他页面、应用切到后台等场景。
typescript
@Entry
@Component
struct MyPage {
onPageShow() {
console.log('页面显示');
}
onPageHide() {
console.log('onPageHide: 页面离开前台');
}
build() {
Column() { /* ... */ }
}
}
触发时机:
- 跳转到另一个页面时(当前页面被覆盖)。
- 应用切到后台(如按 Home 键)。
- 页面被销毁前(先触发
onPageHide,再触发aboutToDisappear)。
适用场景:
- 暂停定时器、动画以节省资源。
- 保存草稿或临时状态。
- 释放不需要前台使用的资源(如相机预览)。
1.3 onBackPress ------ 返回键按下时触发
当用户按下系统返回键(或手势返回)时调用。该钩子可以返回 true 表示拦截返回事件,返回 false 或 undefined 表示不拦截,系统将执行默认返回逻辑。
typescript
@Entry
@Component
struct MyPage {
@State showExitDialog: boolean = false;
onBackPress(): boolean | void {
// 弹出确认对话框,拦截返回
this.showExitDialog = true;
return true;
}
build() {
Column() {
// ...
if (this.showExitDialog) {
// 自定义对话框
}
}
}
}
触发时机:
- 用户点击系统返回键。
- 手势从边缘滑动返回。
适用场景:
- 二次确认退出(如"再按一次退出")。
- 表单未保存时提示用户。
- 自定义返回逻辑(如回退到指定页面而非上一层)。
1.4 页面生命周期执行顺序
页面首次加载:aboutToAppear(组件)→ build(组件)→ onPageShow
跳转到新页面时(旧页面):onPageHide(旧页面)
跳转到新页面时(新页面):aboutToAppear(新页面)→ build → onPageShow(新页面)
从新页面返回时:onBackPress(新页面,可选)→ onPageHide(新页面)→ aboutToDisappear(新页面)→ onPageShow(旧页面)
二、组件经典生命周期
每个用 @Component 装饰的自定义组件都具有生命周期,最基础的两个钩子是 aboutToAppear 和 aboutToDisappear。
2.1 aboutToAppear ------ 组件即将出现
在组件即将被创建并显示之前调用,在 build 方法执行之前触发。
typescript
@Component
struct ChildComponent {
@State data: string = '';
aboutToAppear() {
console.log('aboutToAppear: 组件即将出现');
// 在这里执行初始化操作
this.data = '初始化数据';
// 例如:请求网络数据、注册监听等
}
build() {
Text(this.data)
}
}
触发时机:
- 组件第一次被添加到组件树时。
- 条件渲染中由不可见变为可见时(
if条件从false变为true)。 - 列表项被创建时。
适用场景:
- 获取初始数据(网络请求、数据库查询)。
- 注册事件监听、订阅通知。
- 初始化第三方 SDK。
2.2 aboutToDisappear ------ 组件即将销毁
在组件即将从组件树中移除并销毁之前调用。
typescript
@Component
struct ChildComponent {
aboutToDisappear() {
console.log('aboutToDisappear: 组件即将销毁');
// 执行清理操作
// 例如:取消网络请求、移除监听、释放资源
}
build() {
Text('子组件')
}
}
触发时机:
- 组件从组件树中移除时。
- 条件渲染中由可见变为不可见时(
if条件从true变为false)。 - 页面被销毁时,该页面上所有子组件依次触发
aboutToDisappear。 - 列表项被回收时。
适用场景:
- 取消网络请求,避免内存泄漏。
- 移除事件监听。
- 释放定时器、动画资源。
- 保存临时状态。
2.3 经典生命周期执行顺序示例
typescript
@Entry
@Component
struct LifecycleDemo {
@State showChild: boolean = true;
onPageShow() { console.log('1. onPageShow'); }
onPageHide() { console.log('4. onPageHide'); }
build() {
Column() {
Button('切换子组件').onClick(() => {
this.showChild = !this.showChild;
})
if (this.showChild) {
Child()
}
}
}
}
@Component
struct Child {
aboutToAppear() { console.log('2. Child aboutToAppear'); }
aboutToDisappear() { console.log('3. Child aboutToDisappear'); }
build() {
Text('子组件')
}
}
运行后日志顺序:1. onPageShow → 2. Child aboutToAppear
点击按钮隐藏子组件后:3. Child aboutToDisappear
再次点击显示子组件:2. Child aboutToAppear
点击返回键退出页面:3. Child aboutToDisappear → 4. onPageHide
三、新版组件生命周期
随着 ArkUI 框架的迭代,组件生命周期新增了更细粒度的回调,允许开发者在渲染的更多阶段介入。以下介绍主要的几个新钩子。
3.1 onDidBuild ------ build 执行完成后触发
在组件的 build 方法执行完毕、UI 渲染完成后调用。此时可以安全地操作已经生成的子组件。
typescript
@Component
struct NewLifecycleDemo {
aboutToAppear() {
console.log('1. aboutToAppear');
}
onDidBuild() {
console.log('3. onDidBuild: build 已完成');
// 可在此处执行依赖 UI 已渲染的操作
}
build() {
console.log('2. build');
// UI 构建
Text('新版生命周期示例')
}
}
触发时机:
aboutToAppear→build→onDidBuild,在首次渲染完成后触发。- 当
@State变量变化导致build重新执行后,onDidBuild也会再次触发。
适用场景:
- 获取组件渲染后的实际尺寸或位置。
- 在 UI 就绪后延迟执行某些操作。
- 与第三方 UI 库集成时的桥接代码。
3.2 aboutToReuse ------ 组件复用时触发
在列表或可复用组件池中,当一个已创建的组件实例即将被复用时调用。此钩子允许开发者重置组件状态。
typescript
@Reusable
@Component
struct ReusableListItem {
@State item: string = '';
aboutToReuse(params: Record<string, Object>) {
console.log('aboutToReuse: 组件将被复用, 参数 =', params);
this.item = params['text'] as string; // 根据新数据重置状态
}
build() {
Text(this.item)
.padding(10)
}
}
触发时机:
- 使用
@Reusable装饰的组件,在复用池中取出并复用时。 - 配合
LazyForEach等懒加载场景使用。
适用场景:
- 列表项复用时的状态重置。
- 避免因复用导致显示旧数据的问题。
3.3 onWillApplyTheme ------ 主题变化前触发
当系统主题(如深色/浅色模式)即将变化时调用,允许在主题应用前做准备工作。
typescript
@Component
struct ThemeAwareComponent {
onWillApplyTheme(theme: Theme) {
console.log('onWillApplyTheme: 即将应用新主题', theme);
// 可在此处保存当前主题相关的状态
}
build() {
// 使用新主题渲染
Text('主题感知组件')
}
}
触发时机:
- 系统深色/浅色模式切换时。
- 应用内自定义主题切换时。
适用场景:
- 主题切换前的状态保存。
- 自定义过渡动画的准备。
四、新旧生命周期对比
4.1 触发顺序对比
| 阶段 | 经典生命周期 | 新版生命周期 |
|---|---|---|
| 初始化 | aboutToAppear → build |
aboutToAppear → build → onDidBuild |
| 状态更新 | build |
build → onDidBuild |
| 复用前 | 无 | aboutToReuse(params) |
| 主题切换 | 无 | onWillApplyTheme(theme) |
| 销毁前 | aboutToDisappear |
aboutToDisappear |
4.2 新旧版本关键差异
| 对比维度 | 经典生命周期 | 新版生命周期 |
|---|---|---|
| 钩子数量 | 2 个 | 5+ 个 |
| build 后回调 | 无 | onDidBuild |
| 组件复用 | 不支持 | 支持 aboutToReuse |
| 主题监听 | 需手动实现 | 内置 onWillApplyTheme |
| 学习成本 | 低 | 中 |
| 适用场景 | 简单页面、快速开发 | 复杂应用、高性能列表 |
4.3 选型建议
- 新项目建议直接使用新版生命周期,获得更精细的控制能力。
- 学习时需了解经典生命周期,因为大量现有教程和示例仍基于旧版本。
- 在列表中需要复用优化时,必须使用
@Reusable+aboutToReuse。 - 经典生命周期钩子仍然完全可用,新版是对旧版的增强而非替代。
五、生命周期实验与记忆方法
5.1 日志实验法
创建一个测试页面,在所有生命周期钩子中添加 console.log,通过实际操作观察执行顺序,是掌握生命周期最有效的方法。
typescript
@Entry
@Component
struct LifecycleExperiment {
@State showChild: boolean = true;
onPageShow() { console.log('【页面】onPageShow'); }
onPageHide() { console.log('【页面】onPageHide'); }
onBackPress(): boolean {
console.log('【页面】onBackPress');
return false; // 不拦截
}
build() {
Column({ space: 10 }) {
Text('生命周期实验').fontSize(24)
Button('切换子组件').onClick(() => {
this.showChild = !this.showChild;
})
if (this.showChild) {
Child()
}
}
.width('100%')
.padding(20)
}
}
@Component
struct Child {
aboutToAppear() { console.log(' 【组件·经典】aboutToAppear'); }
aboutToDisappear() { console.log(' 【组件·经典】aboutToDisappear'); }
onDidBuild() { console.log(' 【组件·新版】onDidBuild'); }
build() {
Text('子组件').fontSize(18)
}
}
通过实验,记录以下场景的日志顺序:
- 首次进入页面。
- 点击按钮隐藏/显示子组件。
- 切换到其他页面再返回。
- 按 Home 键切后台再返回。
- 按返回键退出页面。
5.2 关键触发条件速查表
| 钩子 | 触发条件 | 频率 |
|---|---|---|
aboutToAppear |
组件被创建并加入组件树 | 每次创建时一次 |
build |
首次渲染、@State 等状态变化 |
多次 |
onDidBuild |
build 完成后 |
随 build 一同触发 |
aboutToReuse |
复用池取出组件时 | 每次复用时 |
aboutToDisappear |
组件从组件树移除 | 每次移除时一次 |
onPageShow |
页面变为可见 | 每次可见时 |
onPageHide |
页面变为不可见 | 每次不可见时 |
onBackPress |
按下返回键 | 每次返回时 |
六、常见错误与注意事项
6.1 在 aboutToAppear 中执行耗时操作
aboutToAppear 中的同步耗时操作会阻塞 UI 线程,导致页面卡顿甚至白屏。应使用异步方式,或在 onPageShow / onDidBuild 之后分步执行。
6.2 忘记在 aboutToDisappear 中释放资源
未取消的定时器、未移除的事件监听、未关闭的网络连接都可能导致内存泄漏。务必在 aboutToDisappear 中进行清理。
6.3 混淆页面生命周期与组件生命周期
onPageShow/onPageHide只属于@Entry装饰的页面组件,普通@Component没有这两个钩子。aboutToAppear/aboutToDisappear是所有@Component都有的。
6.4 在 build 方法中执行副作用
build 方法应保持为纯渲染函数,不要在其中发起网络请求、修改状态等(可能引发无限循环渲染)。副作用应在 aboutToAppear 或事件回调中处理。
6.5 onBackPress 使用不当导致无法退出
如果 onBackPress 返回 true 却没有提供退出的替代路径,用户将被困在当前页面。务必提供关闭弹窗、切换到其他页面等退出方式。
6.6 复用组件的状态残留
使用 LazyForEach 等列表懒加载时,若未实现 aboutToReuse,可能出现列表项显示旧数据的问题。复用组件应始终在 aboutToReuse 中重置关键状态。
七、小结
| 概念 | 关键点 |
|---|---|
onPageShow |
页面可见时触发,适合刷新数据、恢复定时器 |
onPageHide |
页面不可见时触发,适合暂停任务、保存草稿 |
onBackPress |
返回键按下时触发,可返回 true 拦截 |
aboutToAppear(经典) |
组件创建前初始化,适合网络请求、注册监听 |
aboutToDisappear(经典) |
组件销毁前清理,适合释放资源、取消订阅 |
onDidBuild(新版) |
build 完成后触发,适合获取 UI 尺寸、延迟操作 |
aboutToReuse(新版) |
组件复用时重置状态,配合 @Reusable 使用 |
onWillApplyTheme(新版) |
主题切换前触发,适合保存主题状态 |
生命周期是 HarmonyOS 开发中的核心基础,精确掌握各钩子的触发时机与适用场景,能够在数据请求、资源管理、性能优化等关键环节做出正确决策,避免常见的内存泄漏和 UI 异常问题。
觉得文章有帮助?别忘了:
👍 点赞 👍 -- 给我一点鼓励
⭐ 收藏 ⭐ -- 方便以后查看
🔔 关注 🔔 -- 获取更新通知
标签: #HarmonyOS #ArkUI #生命周期 #页面生命周期 #组件生命周期 #学习笔记 #鸿蒙开发