Ability 生命周期观察:页面什么时候该准备,什么时候该释放

举报
蓝瘦的蜕变 发表于 2026/07/17 18:31:26 2026/07/17
【摘要】 工程化 Demo 里讲生命周期,不应该一上来就写后台任务。先把页面可见生命周期和组件出现/销毁看清楚,后面接文件、通知、分享或系统 Kit 时,才知道初始化、刷新和释放应该放在哪里。 本页只演示四类入口: aboutToAppear:组件即将出现,适合准备轻量状态。 onPageShow:页面重新可见,适合刷新页面内展

Ability 生命周期观察:页面什么时候该准备,什么时候该释放

工程化 Demo 里讲生命周期,不应该一上来就写后台任务。先把页面可见生命周期和组件出现/销毁看清楚,后面接文件、通知、分享或系统 Kit 时,才知道初始化、刷新和释放应该放在哪里。

本页只演示四类入口:

  • aboutToAppear:组件即将出现,适合准备轻量状态。
  • onPageShow:页面重新可见,适合刷新页面内展示。
  • onPageHide:页面隐藏,适合暂停页面内动作。
  • aboutToDisappear:组件即将销毁,适合释放订阅。

交互预期

  • 进入页面后,事件记录里会出现页面 aboutToAppearonPageShow
  • 点击“隐藏子组件”,页面反馈会变化,子组件随后触发 aboutToDisappear
  • 点击“显示子组件”,子组件重新创建,并触发 aboutToAppear
  • 点击“清空记录”,事件列表重置为初始状态。

完整示例代码

class LifecycleRecord {
  index: number
  name: string
  desc: string

  constructor(index: number, name: string, desc: string) {
    this.index = index
    this.name = name
    this.desc = desc
  }
}

@Component
struct LifecycleChildBlock {
  marker: string = ''
  onLifecycle: (eventName: string) => void = (eventName: string) => {}

  aboutToAppear(): void {
    this.onLifecycle('子组件 aboutToAppear')
  }

  aboutToDisappear(): void {
    this.onLifecycle('子组件 aboutToDisappear')
  }

  build() {
    Column({ space: 8 }) {
      Text('可切换子组件')
        .fontSize(17)
        .fontWeight(FontWeight.Bold)
        .fontColor('#111827')
      Text(this.marker)
        .fontSize(13)
        .fontColor('#4B5563')
        .lineHeight(20)
    }
    .width('100%')
    .padding(16)
    .borderRadius(14)
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#BFDBFE' })
    .alignItems(HorizontalAlign.Start)
  }
}

@Entry
@Component
struct AbilityLifecycleDemo {
  @State eventIndex: number = 0
  @State eventLog: string = '等待生命周期事件'
  @State childVisible: boolean = true
  @State childMarker: string = '子组件当前显示。点击下方按钮可以观察子组件出现和销毁。'
  @State feedback: string = '进入页面后会自动记录 aboutToAppear 和 onPageShow。'

  private records: LifecycleRecord[] = [
    new LifecycleRecord(1, 'aboutToAppear', '自定义组件即将出现,适合准备页面内轻量状态。'),
    new LifecycleRecord(2, 'onPageShow', '页面回到前台显示时触发,适合刷新可见状态。'),
    new LifecycleRecord(3, 'onPageHide', '页面被遮挡或跳走时触发,适合暂停页面内动作。'),
    new LifecycleRecord(4, 'aboutToDisappear', '组件即将销毁时触发,适合释放页面内订阅。')
  ]

  aboutToAppear(): void {
    this.appendEvent('页面 aboutToAppear')
  }

  aboutToDisappear(): void {
    this.appendEvent('页面 aboutToDisappear')
  }

  onPageShow(): void {
    this.appendEvent('页面 onPageShow')
  }

  onPageHide(): void {
    this.appendEvent('页面 onPageHide')
  }

  private appendEvent(eventName: string): void {
    this.eventIndex += 1
    const timeText: string = new Date().toTimeString().slice(0, 8)
    this.eventLog = `${this.eventIndex}. ${timeText} ${eventName}\n${this.eventLog}`
    this.feedback = `最近事件:${eventName}`
  }

  private toggleChild(): void {
    if (this.childVisible) {
      this.childVisible = false
      this.childMarker = '子组件已隐藏。再次点击会重新创建子组件。'
      this.feedback = '已请求隐藏子组件,随后会触发子组件 aboutToDisappear。'
    } else {
      this.childVisible = true
      this.childMarker = '子组件已重新显示。'
      this.feedback = '已请求显示子组件,随后会触发子组件 aboutToAppear。'
    }
  }

  private clearLog(): void {
    this.eventIndex = 0
    this.eventLog = '已清空,继续切换页面或子组件可重新观察。'
    this.feedback = '生命周期记录已清空。'
  }

  @Builder
  recordCard(index: number) {
    Column({ space: 6 }) {
      Text(this.records[index].name)
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .fontColor('#111827')
      Text(this.records[index].desc)
        .fontSize(13)
        .fontColor('#4B5563')
        .lineHeight(20)
    }
    .width('100%')
    .padding(14)
    .borderRadius(12)
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#E5E7EB' })
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 20 }) {
        Column({ space: 8 }) {
          Text('Ability 生命周期观察')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text('先看页面可见生命周期,不做后台任务。')
            .fontSize(15)
            .fontColor('#4B5563')
            .lineHeight(22)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        Column({ space: 10 }) {
          ForEach(this.records, (item: LifecycleRecord, index: number) => {
            this.recordCard(index)
          }, (item: LifecycleRecord) => item.name)
        }
        .width('100%')

        if (this.childVisible) {
          LifecycleChildBlock({
            marker: this.childMarker,
            onLifecycle: (eventName: string) => {
              this.appendEvent(eventName)
            }
          })
        }

        Row({ space: 10 }) {
          Button(this.childVisible ? '隐藏子组件' : '显示子组件')
            .height(48)
            .layoutWeight(1)
            .fontSize(15)
            .backgroundColor('#2563EB')
            .onClick(() => {
              this.toggleChild()
            })
          Button('清空记录')
            .height(48)
            .layoutWeight(1)
            .fontSize(15)
            .backgroundColor('#0F766E')
            .onClick(() => {
              this.clearLog()
            })
        }
        .width('100%')

        Text(this.feedback)
          .width('100%')
          .fontSize(14)
          .fontColor('#1D4ED8')
          .lineHeight(22)
          .padding(12)
          .backgroundColor('#EFF6FF')
          .borderRadius(10)

        Column({ space: 8 }) {
          Text('事件记录')
            .fontSize(18)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text(this.eventLog)
            .fontSize(13)
            .fontColor('#4B5563')
            .lineHeight(22)
        }
        .width('100%')
        .padding(16)
        .borderRadius(14)
        .backgroundColor('#FFFFFF')
        .border({ width: 1, color: '#E5E7EB' })
        .alignItems(HorizontalAlign.Start)
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8FAFC')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。