@entry和@Component的生命周期
- @entry和@Component的关系
- @Component生命周期
- @Entry生命周期
- 生命周期流程图
- 生命周期展示示例代码
- 参考资料
HarmonyOS的生命周期可以分为@Compnent的生命周期和@Entry的生命周期,也就是自定义组件的生命周期和页面的生命周期。
@entry和@Component的关系
@Component生命周期
@Component即自定义组件,可以组合多个系统组件实现UI的复用,可以调用组件的生命周期。其生命周期有2个:
aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
aboutToDisappear:aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。不建议在生命周期aboutToDisappear内使用async await,如果在生命周期的aboutToDisappear使用异步操作(Promise或者回调方法),自定义组件将被保留在Promise的闭包中,直到回调方法被执行完,这个行为阻止了自定义组件的垃圾回收。
@Entry生命周期
@Entry即应用的UI页面。可以由一个或者多个自定义组件组成,@Entry装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个@Entry。只有被@Entry装饰的组件才可以调用页面的生命周期。其生命周期有三个方法
onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景。
onPageHide:页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。
onBackPress:当用户点击返回按钮时触发。
生命周期流程图
生命周期流程如下图所示,下图展示的是被@Entry装饰的组件(页面)生命周期。
可以看出先执行@Compent组件的aboutToAppear和build,然后在执行@Entry的onPageShow.逻辑也很简单,只有先构建@Component组件,整个UI才能展示出来。
生命周期展示示例代码
以下示例展示了生命周期的调用时机:
// Index.ets
import router from '@ohos.router';
struct MyComponent { showChild: boolean = true; btnColor:string = "#FF007DFF"// 只有被@Entry装饰的组件才可以调用页面的生命周期onPageShow() {console.info('Index onPageShow');}// 只有被@Entry装饰的组件才可以调用页面的生命周期onPageHide() {console.info('Index onPageHide');}// 只有被@Entry装饰的组件才可以调用页面的生命周期onBackPress() {console.info('Index onBackPress');this.btnColor ="#FFEE0606"return true // 返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理}// 组件生命周期aboutToAppear() {console.info('MyComponent aboutToAppear');}// 组件生命周期aboutToDisappear() {console.info('MyComponent aboutToDisappear');}build() {Column() {// this.showChild为true,创建Child子组件,执行Child aboutToAppearif (this.showChild) {Child()}// this.showChild为false,删除Child子组件,执行Child aboutToDisappearButton('delete Child').margin(20).backgroundColor(this.btnColor).onClick(() => {this.showChild = false;})// push到page页面,执行onPageHideButton('push to next page').onClick(() => {router.pushUrl({ url: 'pages/page' });})}}
}
struct Child { title: string = 'Hello World';// 组件生命周期aboutToDisappear() {console.info('[lifeCycle] Child aboutToDisappear')}// 组件生命周期aboutToAppear() {console.info('[lifeCycle] Child aboutToAppear')}build() {Text(this.title).fontSize(50).margin(20).onClick(() => {this.title = 'Hello ArkUI';})}
}//第二个页面 page.ets
struct page { textColor: Color = Color.Black; num: number = 0onPageShow() {this.num = 5}onPageHide() {console.log("page onPageHide");}onBackPress() { // 不设置返回值按照false处理this.textColor = Color.Greythis.num = 0}aboutToAppear() {this.textColor = Color.Blue}build() {Column() {Text(`num 的值为:${this.num}`).fontSize(30).fontWeight(FontWeight.Bold).fontColor(this.textColor).margin(20).onClick(() => {this.num += 5})}.width('100%')}
}
以上示例中,Index
页面包含两个自定义组件:
-
一个是被@Entry装饰的
MyComponent
,也是页面的入口组件,即页面的根节点; -
一个是Child,是MyComponent的子组件。
-
应用冷启动的初始化流程为:
MyComponent aboutToAppear --> MyComponent build --> Child aboutToAppear --> Child build --> Child build执行完毕 --> MyComponent build执行完毕 --> Index onPageShow。
-
点击“delete Child”,if绑定的this.showChild变成false,删除Child组件,会执行
Child aboutToDisappear
方法。谁消失就执行谁的 aboutToDisapper方法 -
点击“push to next page”,调用router.pushUrl接口,跳转到另外一个页面,当前Index页面隐藏,执行页面生命周期Index onPageHide。此处调用的是router.pushUrl接口,Index页面被隐藏,并没有销毁,所以只调用
onPageHide
。跳转到新页面后,执行初始化新页面的生命周期的流程。 -
如果调用的是router.replaceUrl,则当前Index页面被销毁,执行的生命周期流程将变为:
Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear
。可以看出组件的销毁是从组件树上直接摘下子树,所以先调用父组件的aboutToDisappear,再调用子组件的aboutToDisappear,(所谓皮之不存毛将焉附),然后执行初始化新页面的生命周期流程。 -
点击返回按钮,触发页面生命周期Index onBackPress,且触发返回一个页面后会导致当前Index页面被销毁。
-
最小化应用或者应用进入后台,触发Index onPageHide。当前Index页面没有被销毁,所以并不会执行组件的aboutToDisappear。应用回到前台,执行Index onPageShow。
-
退出应用,执行
Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。
参考资料
页面和自定义组件生命周期