写点什么

鸿蒙自定义组件生命周期

作者:龙儿筝
  • 2024-11-10
    上海
  • 本文字数:2705 字

    阅读完需:约 9 分钟

在开始之前,我们先明确自定义组件和页面的关系:


  • 自定义组件:@Component 装饰的 UI 单元,可以组合多个系统组件实现 UI 的复用,可以调用组件的生命周期。

  • 页面:即应用的 UI 页面。可以由一个或者多个自定义组件组成,@Entry 装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个 @Entry。只有被 @Entry 装饰的组件才可以调用页面的生命周期。


页面生命周期,即被 @Entry 装饰的组件生命周期,提供以下生命周期接口:


  • onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景。

  • onPageHide:页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。

  • onBackPress:当用户点击返回按钮时触发。


组件生命周期,即一般用 @Component 装饰的自定义组件的生命周期,提供以下生命周期接口:


  • aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其 build()函数之前执行。

  • onDidBuild:组件 build()函数执行完成之后回调该接口,不建议在 onDidBuild 函数中更改状态变量、使用 animateTo 等功能,这可能会导致不稳定的 UI 表现。

  • aboutToDisappear:aboutToDisappear 函数在自定义组件析构销毁之前执行。不允许在 aboutToDisappear 函数中改变状态变量,特别是 @Link 变量的修改可能会导致应用程序行为不稳定。


生命周期流程如下图所示,下图展示的是被 @Entry 装饰的组件(页面)生命周期。



以下示例展示了生命周期的调用时机:


// Index.etsimport { router } from '@kit.ArkUI';
@Entry@Componentstruct MyComponent { @State showChild: boolean = true; @State 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'); }
// 组件生命周期 onDidBuild() { console.info('MyComponent onDidBuild'); }
// 组件生命周期 aboutToDisappear() { console.info('MyComponent aboutToDisappear'); }
build() { Column() { // this.showChild为true,创建Child子组件,执行Child aboutToAppear if (this.showChild) { Child() } // this.showChild为false,删除Child子组件,执行Child aboutToDisappear Button('delete Child') .margin(20) .backgroundColor(this.btnColor) .onClick(() => { this.showChild = false; }) // push到page页面,执行onPageHide Button('push to next page') .onClick(() => { router.pushUrl({ url: 'pages/page' }); }) } }}
@Componentstruct Child { @State title: string = 'Hello World'; // 组件生命周期 aboutToDisappear() { console.info('[lifeCycle] Child aboutToDisappear'); }
// 组件生命周期 onDidBuild() { console.info('[lifeCycle] Child onDidBuild'); }
// 组件生命周期 aboutToAppear() { console.info('[lifeCycle] Child aboutToAppear'); }
build() { Text(this.title) .fontSize(50) .margin(20) .onClick(() => { this.title = 'Hello ArkUI'; }) }}
// page.ets@Entry@Componentstruct page { @State textColor: Color = Color.Black; @State num: number = 0;
onPageShow() { this.num = 5; }
onPageHide() { console.log("page onPageHide"); }
onBackPress() { // 不设置返回值按照false处理 this.textColor = Color.Grey; this.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 的子组件。只有 @Entry 装饰的节点才可以使页面级别的生命周期方法生效,因此在 MyComponent 中声明当前 Index 页面的页面生命周期函数(onPageShow / onPageHide / onBackPress)。MyComponent 和其子组件 Child 分别声明了各自的组件级别生命周期函数(aboutToAppear / onDidBuild/aboutToDisappear)。


  • 应用冷启动的初始化流程为:MyComponent aboutToAppear --> MyComponent build --> MyComponent onDidBuild--> Child aboutToAppear --> Child build --> Child onDidBuild --> Index onPageShow。

  • 点击“delete Child”,if 绑定的 this.showChild 变成 false,删除 Child 组件,会执行 Child aboutToDisappear 方法。

  • 点击“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。


发布于: 刚刚阅读数: 4
用户头像

龙儿筝

关注

还未添加个人签名 2024-10-27 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙自定义组件生命周期_鸿蒙_龙儿筝_InfoQ写作社区