组件生命周期是在鸿蒙ArkUI中声明式开发范式中特有的。
自定义组件的生命周期
自定义组件的生命周期回调函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。一共有(2+3+2)个生命周期钩子函数。
允许在生命周期函数中使用Promise和异步回调函数,比如网络资源获取,定时器设置等。
1. 组件(只有@Components修饰)生命周期函数:
1.1. aboutToAppear
aboutToAppear?(): void
aboutToAppear函数在创建自定义组件的新实例后,在执行其build()函数之前执行。允许在aboutToAppear函数中改变状态变量,更改将在后续执行build()函数中生效。
1.2. aboutToDisappear
aboutToDisappear?(): void
aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。
2. 页面(@Entry修饰的组件)特有的3个生命周期函数
2.1. onPageShow
onPageShow?(): void
页面每次显示时触发一次,包括路由过程、应用进入前台等场景,仅@Entry装饰的自定义组件生效。
2.2. onPageHide
onPageHide?(): void
页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景,仅@Entry装饰的自定义组件生效。
2.3. onBackPress
onBackPress?(): void | boolean
当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。
@Entry
@Component
struct IndexComponent {
@State textColor: Color = Color.Black;
onPageShow() {
this.textColor = Color.Blue;
console.info('IndexComponent onPageShow');
}
onPageHide() {
this.textColor = Color.Transparent;
console.info('IndexComponent onPageHide');
}
onBackPress() {
this.textColor = Color.Red;
console.info('IndexComponent onBackPress');
}
build() {
Column() {
Text('Hello World')
.fontColor(this.textColor)
.fontSize(30)
.margin(30)
}.width('100%')
}
}
3. 复用组件(加了@Reusable装饰器的组件)生命周期函数:
3.1. aboutToReuse10+
组件的生命周期回调,在可复用组件从复用缓存中加入到组件树之前调用,可在其中更新组件的状态变量以展示正确的内容,入参的类型与自定义组件的构造函数入参相同。
aboutToReuse?(params: { [key: string]: unknown }): void;
参数名 | 类型 | 说明 |
---|---|---|
params | { [key: string]: unknown } | 自定义组件的构造参数。 |
3.2. aboutToRecycle10+
组件的生命周期回调
,在可复用组件
从组件树
上被加入到复用缓存
之前调用。
aboutToRecycle?(): void;
参考代码:
export class Message {
value: string | undefined;
constructor(value: string) {
this.value = value
}
}
@Entry
@Component
struct Index {
@State switch: boolean = true
build() {
Column() {
Button('Hello World')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.switch = !this.switch
})
if (this.switch) {
Child({ message: new Message('Child') })
}
}
.height("100%")
.width('100%')
}
}
@Reusable
@Component
struct Child {
@State message: Message = new Message('AboutToReuse');
aboutToReuse(params: Record<string, ESObject>) {
console.info("Recycle Child")
this.message = params.message as Message
}
aboutToReuse(params: Record<string, ESObject>) {
console.log("LifeCycle_aboutToReuse:", "组件准备挂载到组件树")
console.log("LifeCycle_params:", JSON.stringify(params))
this.message = params.message as Message
}
aboutToRecycle(): void {
console.log("LifeCycle_aboutToRecycle:", "组件即将进入复用缓存")
}
build() {
Column() {
Text(this.message.value)
.fontSize(20)
}
.borderWidth(2)
.height(100)
}
}
组件复用生效的条件是:
-
自定义组件被
@Reusable
装饰器修饰,即表示其具备组件复用的能力; -
在一个自定义组件(父)下创建出来的具备组件复用能力的自定义组件(子),在可复用自定义组件从组件树上移除之后,会被加入到其父自定义组件的可复用组件缓存中;
-
在一个自定义组件(父)下创建可复用的子组件时,若可复用子节点缓存中有对应类型的可复用子组件的实例,会通过更新可复用子组件的方式,快速创建可复用子组件。
复用组件的注意:
-
@Reusable
标识自定义组件具备可复用的能力,它可以被添加到任意的自定义组件上,但是开发者需要小心处理自定义组件的创建流程
和更新流程
以确保自定义组件在复用之后能展示出正确的行为; -
可复用自定义组件的缓存和复用只能发生在同一父组件下,无法在不同的父组件下复用同一自定义组件的实例。例如,A组件是可复用组件,其也是B组件的子组件,并进入了B组件的可复用组件缓存中,但是在C组件中创建A组件时,无法使用B组件缓存的A组件;
-
@Reusable
装饰器只需要对复用子树的根节点进行标记。例如:自定义组件A中有一个自定义子组件B,若需要复用A与B的子树,只需要对A组件添加@Reusable
装饰器。 -
可复用自定义组件中嵌套自定义组件,如果想要对嵌套的子组件的内容进行更新,需要实现对应子组件的
aboutToReuse
生命周期回调。例如:A组件是可复用的组件,B是A中嵌套的子组件,要想实现对A组件中的B组件内容进行更新,需要在B组件中实现aboutToReuse
生命周期回调。 -
自定义组件的复用带来的性能提升主要体现在节省了自定义组件的JS对象的创建时间并复用了自定义组件的组件树结构,若应用开发者在自定义组件复用的前后使用渲染控制语法显著的改变了自定义组件的组件树结构,那么将无法享受到组件复用带来的性能提升;
-
组件复用仅发生在存在可复用组件从组件树上移除并再次加入到组件树的场景中,若不存在上述场景,将无法触发组件复用。例如,使用ForEach渲染控制语法创建可复用的自定义组件,由于ForEach渲染控制语法的全展开属性,不能触发组件复用。
-
组件复用当前不支持嵌套使用。即在可复用的组件的子树中存在可复用的组件,可能导致未定义的结果。