渐进式编程课
鸿蒙 目录
第 16 课2026.07.24

适用场景:组件显示时启动定时任务、订阅或加载数据,并在组件离开时及时停止任务、解除订阅

第 16 课:组件生命周期与资源清理

  • 日期:2026-07-24
  • 知识点:aboutToAppear、aboutToDisappear
  • 适用场景:组件显示时启动定时任务、订阅或加载数据,并在组件离开时及时停止任务、解除订阅

承接上一课的 @Watch:上一课处理“状态变化时做什么”;这一课处理“组件进入或离开页面时做什么”。二者触发条件不同,生命周期方法不能用状态监听代替。

1. 进入时启动,离开时清理

组件即将显示时会调用 aboutToAppear(),适合初始化数据或启动资源;组件即将销毁时会调用 aboutToDisappear(),适合释放对应资源。

应当把启动和清理成对设计:

text
aboutToAppear
-> 启动定时器或订阅
-> 状态变化
-> UI 自动刷新
-> aboutToDisappear
-> 清理定时器或取消订阅

如果只启动不清理,离开页面后任务仍可能继续运行,造成重复回调或资源浪费。

2. 最小示例

ts
@Entry
@Component
struct TimerPage {
  @State seconds: number = 0;
  private timerId: number = -1;

  aboutToAppear(): void {
    this.timerId = setInterval(() => {
      this.seconds++;
    }, 1000);
  }

  aboutToDisappear(): void {
    if (this.timerId !== -1) {
      clearInterval(this.timerId);
      this.timerId = -1;
    }
  }

  build() {
    Column({ space: 16 }) {
      Text(`页面已显示 ${this.seconds} 秒`)
        .fontSize(22)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

seconds 是驱动 UI 的状态;timerId 只是资源句柄,不需要参与渲染。页面离开时清理定时器,避免下一次进入页面后出现多个定时器同时运行。

3~5 分钟练习

在示例中增加一个 @State running: boolean = false:

  1. 组件显示并启动定时器后,将 running 设为 true。
  2. 组件离开并清理定时器后,将 running 设为 false。
  3. 页面显示“计时中”或“已停止”。

参考答案

ts
@Entry
@Component
struct TimerPage {
  @State seconds: number = 0;
  @State running: boolean = false;
  private timerId: number = -1;

  aboutToAppear(): void {
    this.timerId = setInterval(() => {
      this.seconds++;
    }, 1000);
    this.running = true;
  }

  aboutToDisappear(): void {
    if (this.timerId !== -1) {
      clearInterval(this.timerId);
      this.timerId = -1;
    }
    this.running = false;
  }

  build() {
    Column({ space: 16 }) {
      Text(this.running ? '计时中' : '已停止')
      Text(`${this.seconds} 秒`)
    }
  }
}

与上一课的联系

上一课的 @Watch 在指定状态变化时执行联动逻辑;本课的生命周期方法由组件进入、离开触发。以后接入事件订阅、网络监听或传感器时,都应先确认资源在哪个生命周期启动,再在对应的离开生命周期中清理。