做 ArkUI / ArkTS 的时候,很多问题表面看起来像是:

  • 为什么 UI 没及时刷新?
  • 为什么返回键拦截不生效?
  • 为什么列表一滑就掉帧?
  • 为什么组件销毁后还在报错?

其实大多数都和一个东西有关:生命周期放错地方了

这篇就不写太“官方文档翻译”的风格,直接按平时开发会遇到的场景来讲,尽量让你看完就知道“这段逻辑该放哪”。


先说结论:生命周期不是背下来,而是知道“谁负责什么”

ArkUI 里常用生命周期可以分成几类:

1)组件创建 / 销毁相关

  • aboutToAppear
  • onDidBuild(API 12+)
  • aboutToDisappear

2)页面(@Entry)相关

  • onPageShow
  • onPageHide
  • onBackPress
  • onNewParam(API 19+,单实例路由常用)

3)复用组件(性能优化重点)

  • aboutToReuse
  • aboutToRecycle

4)主题相关

  • onWillApplyTheme(API 12+)

5)卡片相关

  • onFormRecycle
  • onFormRecover

另外还有个不是生命周期、但必须有的:

  • build():定义 UI 的地方

一、build():这个不是“做逻辑”的地方,是“描述 UI”的地方

build() 是每个自定义组件都要写的。

它的职责很简单:组件长什么样
状态变了以后,框架会重新根据 build() 去更新 UI。

所以平时常见误区是:

  • build() 里写初始化逻辑
  • build() 里做重计算
  • build() 里发请求

这些都不太合适。build() 尽量保持“干净”,让它只负责 UI 描述。


二、组件生命周期(最常用):aboutToAppear / onDidBuild / aboutToDisappear

这三个是日常写组件最常用的。


1)aboutToAppear:组件实例创建后、build 前触发

这个阶段很好理解:组件要出现了

它的特点是:

  • build() 前触发
  • 允许修改状态变量
  • 你在这里改的状态,后面的 build() 可以直接用到

适合放什么

  • 轻量初始化(默认值、标记位)
  • 读取缓存(轻量)
  • 启动定时器(记得后面清理)
  • 发起异步请求(可以,但不要阻塞)

不建议放什么

  • 高耗时计算
  • 大量同步逻辑
  • 会卡主线程的操作

因为很多场景下组件会频繁创建销毁(比如列表项、条件渲染),aboutToAppear 会被反复调用。这里一旦写重了,卡顿会非常明显。


2)onDidBuild(API 12+):build 执行后触发

这个回调很适合做一类事:不影响当前 UI 的逻辑

比如:

  • 埋点上报
  • 打日志
  • 调试输出

简单说就是:
如果这段逻辑不需要参与这次 UI 渲染,那放 onDidBuild 会更顺手。


3)aboutToDisappear:组件销毁时触发

这个阶段就一个核心原则:

只清理,不改状态。

尤其是不要在这里改 @Link,容易导致不稳定行为。

适合放什么

  • 清除定时器
  • 解绑监听
  • 释放资源引用
  • 停掉异步任务/订阅(如果你有管理)

不要做什么

  • 修改状态变量让 UI 再刷新
  • 做高耗时阻塞操作

三、页面生命周期(只对 @Entry 页面生效)

这个一定要分清,不然会经常写错地方。

onPageShow / onPageHide / onBackPress / onNewParam 这些是页面级生命周期,只对 @Entry 装饰的路由页面有效,不是普通组件都有。


1)onPageShow:页面显示时触发

触发场景包括:

  • 路由跳转到这个页面
  • 应用从后台回前台,这个页面重新显示

适合放什么

  • 页面曝光埋点
  • 恢复页面状态
  • 轻量刷新逻辑
  • 恢复动画/计时器

2)onPageHide:页面隐藏时触发

触发场景包括:

  • 跳转到别的页面
  • 应用进入后台

适合放什么

  • 暂停动画
  • 暂停计时器
  • 异步释放重资源(相机、播放器等)

这里也建议别做重的同步操作,不然切页面的时候会卡。


3)onBackPress:拦截返回键(页面级)

这个在做“二次确认退出”“先关弹窗再返回”时特别常用。

返回规则很简单:

  • true:你自己处理,不走默认返回
  • false:走默认返回逻辑
  • 不写返回值:默认按 false

一个常见用法

页面上有弹层时,优先关闭弹层,不直接退出页面。


4)onNewParam(API 19+):单实例页面收到新参数

这个不是每次路由都会触发,它只在一个场景下出现:

  • 页面本来就在路由栈里
  • 这次用单实例模式(Single)把它移到栈顶
  • 同时传了新参数

这时候不会重新创建页面,而是触发 onNewParam(param)

适合做什么

  • 更新页面内容
  • 根据新参数刷新状态
  • 做“复用页面实例”的场景优化

这个回调对做路由优化很有用,不然很多人会以为“怎么没重新走 aboutToAppear”。


四、复用组件生命周期(列表优化重点)

如果你在做列表、瀑布流、滑动卡片,这组生命周期很重要。


1)aboutToReuse:从复用池里拿出来重新用

当组件被标记为可复用(比如 @Reusable),它从复用缓存重新加入节点树时会触发这个回调。

适合做什么

  • 用新参数更新显示内容
  • 刷新本次复用需要的状态

注意点(很关键)

  • 高频触发(尤其滑动场景)
  • 不要写耗时逻辑,否则很容易掉帧
  • @Link / @ObjectLink / @Prop 这类自动更新的变量,不要重复乱赋值

一句话:
这里是“快速换内容”的地方,不是“做重活”的地方。


2)aboutToRecycle:进入复用池前触发

组件从组件树上移除、准备进复用缓存前会触发。

适合做什么

  • 清理占内存的引用
  • 停掉非必要任务
  • 避免内存一直被占着

这个回调写得好不好,直接关系到列表长时间滑动后的内存表现。


3)状态管理 V2 的复用(API 18+)

@ComponentV2 + @ReusableV2 场景里也有 aboutToReuse(),思路一样:

  • 组件被复用时做必要恢复
  • 依然别写重逻辑

本质没变,还是那句话:复用回调追求快


五、onWillApplyTheme(API 12+):主题适配很好用

这个回调很多人没用过,但其实很实用,尤其是做深浅色 / 品牌色适配的时候。

它的触发时机是:

  • 组件新实例创建后
  • build()
  • 会给你当前组件上下文的 Theme

而且这里允许改状态变量,改完后 build() 直接生效。

适合场景

  • 根据 Theme 提前设置组件颜色
  • 自定义主题切换时同步状态
  • 把配色逻辑集中起来,不要散在 build() 里一堆 if/else

如果你项目后面会做统一主题,这个回调会非常顺手。


六、pageTransition(API 9+):页面转场动画

这个生命周期是做页面进入/离开动画的。

如果你有页面切换动画需求,建议在这里统一处理,而不是把动画逻辑散在按钮点击事件里。后期维护会轻松很多。


七、卡片生命周期:onFormRecycle / onFormRecover(做 ArkTS 卡片时会用到)

如果你有卡片(Form)场景,这两个回调要知道。

1)onFormRecycle

卡片被回收时触发,可以返回一个字符串,交给卡片管理服务代保存。

你可以理解成:
“卡片被系统收走前,我先存一点状态。”

2)onFormRecover

卡片恢复时触发,会拿到之前保存的那段字符串。

你可以理解成:
“卡片回来了,把上次状态拿回来恢复一下。”

适合保存的是轻量状态,比如:

  • 当前选中的 tab
  • 某个 id
  • 简单的展示状态

不建议塞太大的内容。


八、生命周期里能不能写异步?可以,但别乱放

官方说明里允许在生命周期函数中使用 Promise / 异步回调(比如网络请求、定时器等),这个在实际开发里非常常见。

但“能写”不代表“哪里都适合写”。

比较稳的写法

  • aboutToAppear 里发起异步请求(轻量触发)
  • 回来后更新状态
  • aboutToDisappear / onPageHide 做清理(停定时器、解绑订阅等)

不太稳的写法

  • 在高频回调(比如 aboutToReuse)里反复发请求
  • 组件都销毁了,异步结果回来还在更新状态
  • 在生命周期里做同步重计算导致主线程卡住

九、实际开发里最容易踩的几个坑(真的很常见)

坑 1:在 aboutToDisappear 里改状态

表现通常是:

  • 行为不稳定
  • 偶发报错
  • 数据链路怪怪的

解决思路:
销毁阶段只清理,不做 UI 状态更新。


坑 2:aboutToAppear 里塞太多东西

尤其是频繁创建销毁的组件,直接导致:

  • 页面卡顿
  • 列表掉帧
  • 点击响应慢

解决思路:
初始化可以做,但尽量轻量;重逻辑缓存化、异步化。


坑 3:把页面逻辑写在普通组件里

比如:

  • 想在普通组件里处理前后台切换
  • 想在普通组件里拦截返回键

结果当然是行为不符合预期。

记住:

  • 页面显示/隐藏:onPageShow / onPageHide
  • 返回键:onBackPress
  • 且这些是 @Entry 页面级的

坑 4:复用回调里做重逻辑

你在列表里滑动时,aboutToReuse 会被频繁调用。
这里一旦做重活,帧率会掉得很明显。

解决思路:
复用回调只做必要更新,别做重计算、别做复杂阻塞操作。


十、一个很好用的“职责分工”记法(推荐直接记)

组件级

  • aboutToAppear:轻初始化
  • onDidBuild:build 后补充(日志/埋点)
  • aboutToDisappear:清理资源

页面级(@Entry)

  • onPageShow:页面显示后的恢复/刷新
  • onPageHide:页面隐藏时暂停/异步释放
  • onBackPress:返回键拦截
  • onNewParam:单实例页面拿新参数

复用组件

  • aboutToReuse:复用时更新内容
  • aboutToRecycle:进复用池前清理

主题

  • onWillApplyTheme:拿 Theme,提前设置状态

卡片

  • onFormRecycle:回收前保存状态
  • onFormRecover:恢复后还原状态

十一、给新手的学习顺序(这样学最快)

如果你是刚开始接触,不用一口气全背,按这个顺序就行:

第一阶段(先够用)

  • build
  • aboutToAppear
  • aboutToDisappear
  • onBackPress

第二阶段(页面体验)

  • onPageShow
  • onPageHide

第三阶段(性能优化)

  • aboutToReuse
  • aboutToRecycle

第四阶段(进阶)

  • onWillApplyTheme
  • onDidBuild
  • onNewParam

第五阶段(特定场景)

  • onFormRecycle
  • onFormRecover
  • pageTransition

最后一句(也是这篇的核心)

很多“看起来像玄学”的问题,其实不是框架抽风,而是生命周期职责混了:

  • 初始化太重 → 卡
  • 销毁时改状态 → 不稳
  • 复用回调做重活 → 掉帧
  • 页面逻辑写到普通组件 → 不生效

把生命周期当成不同工位来用,代码会明显顺很多,后面排查问题也快很多。

标签: none

添加新评论