HarmonyOS 页面生命周期与组件生命周期

本文献给:

已掌握状态管理基础、能独立完成组件间数据通信的鸿蒙开发者。本文将系统讲解 HarmonyOS 中页面生命周期与组件生命周期的各个钩子函数,涵盖触发时机、执行顺序以及新旧版本组件生命周期的差异对比,帮助你精确掌控应用运行的关键节点。

你将学到:

  1. 页面生命周期钩子(onPageShow、onPageHide、onBackPress)的触发时机与应用
  2. 组件经典生命周期(aboutToAppear、aboutToDisappear)的调用时机
  3. 新版组件生命周期新增钩子的作用
  4. 新旧版本组件生命周期的对比与选型建议
  5. 通过日志实验追踪生命周期执行顺序
  6. 各钩子函数的适用场景与常见错误

目录

  • 一、页面生命周期
    • [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 表示拦截返回事件,返回 falseundefined 表示不拦截,系统将执行默认返回逻辑。

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(新页面)→ buildonPageShow(新页面)

从新页面返回时:onBackPress(新页面,可选)→ onPageHide(新页面)→ aboutToDisappear(新页面)→ onPageShow(旧页面)

二、组件经典生命周期

每个用 @Component 装饰的自定义组件都具有生命周期,最基础的两个钩子是 aboutToAppearaboutToDisappear

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. onPageShow2. Child aboutToAppear

点击按钮隐藏子组件后:3. Child aboutToDisappear

再次点击显示子组件:2. Child aboutToAppear

点击返回键退出页面:3. Child aboutToDisappear4. 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('新版生命周期示例')
  }
}

触发时机:

  • aboutToAppearbuildonDidBuild,在首次渲染完成后触发。
  • @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 触发顺序对比

阶段 经典生命周期 新版生命周期
初始化 aboutToAppearbuild aboutToAppearbuildonDidBuild
状态更新 build buildonDidBuild
复用前 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)
  }
}

通过实验,记录以下场景的日志顺序:

  1. 首次进入页面。
  2. 点击按钮隐藏/显示子组件。
  3. 切换到其他页面再返回。
  4. 按 Home 键切后台再返回。
  5. 按返回键退出页面。

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 #生命周期 #页面生命周期 #组件生命周期 #学习笔记 #鸿蒙开发

相关推荐
金启攻1 小时前
【鸿蒙原生应用开发实战】第五篇:收藏管理与个人中心 — 收尾两个关键页面的完整实现
华为·harmonyos
无限码力1 小时前
华为非AI方向笔试真题 - 楼内救人
算法·华为·华为非ai方向笔试真题·华为笔试真题·华为算法题
金启攻1 小时前
【鸿蒙原生应用开发实战】第三篇:列表页与标签筛选功能 — 打造高效的天体列表
华为·harmonyos
无限码力1 小时前
华为非AI方向笔试真题 - 容器镜像平均大小统计
算法·华为·华为非ai方向笔试真题·华为笔试真题·华为非ai笔试真题·华为0612非ai笔试真题
Keep_Trying_Go1 小时前
华为开源框架MindSpore基本使用
华为·开源
无限码力1 小时前
华为非AI方向0612笔试真题-循环异或加密器(详细思路+多语言题解)
算法·华为·华为非ai方向笔试真题·华为笔试真题·华为0612笔试真题
烛衔溟2 小时前
HarmonyOS 工程目录、配置文件与 Stage 模型核心
华为·harmonyos
祭曦念2 小时前
【共创季稿事节】鸿蒙原生 ArkTS 布局:NavRouter + NavDestination 导航布局实战
ubuntu·华为·harmonyos
木咺吟11 小时前
鸿蒙原生应用实战(一):从零搭建快递追踪App——项目初始化与工程架构详解
华为·harmonyos