自定义组件和页面的联系:

  • 自定义组件:@Component装修的UI单元,能够组合多个体系组件完成UI的复用,能够调用组件的生命周期。
  • 页面:即运用的UI页面。能够由一个或许多个自定义组件组成,@Entry装修的自定义组件为页面的进口组件,即页面的根节点,一个页面有且仅能有一个@Entry。只要被@Entry装修的组件才能够调用页面的生命周期。

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

  • onPageShow:页面每次显现时触发一次,包括路由进程、运用进入前台等场景。
  • onPageHide:页面每次躲藏时触发一次,包括路由进程、运用进入后台等场景。
  • onBackPress:当用户点击回来按钮时触发。

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

  • aboutToAppear:组件即将出现时回调该接口,具体机遇为在创立自定义组件的新实例后,在履行其build()函数之前履行。
  • aboutToDisappear:在自定义组件析构毁掉之前履行。不允许在aboutToDisappear函数中改动状况变量,特别是@Link变量的修正可能会导致运用程序行为不稳定。

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

鸿蒙(HarmonyOS)开发——认识页面和自定义组件生命周期

依据上面的流程图,我们从自定义组件的初始创立、从头烘托和删去来具体解释。

自定义组件的创立和烘托流程

  1. 自定义组件的创立:自定义组件的实例由ArkUI结构创立。
  2. 初始化自定义组件的成员变量:通过本地默认值或许结构办法传递参数来初始化自定义组件的成员变量,初始化顺序为成员变量的定义顺序。
  3. 假如开发者定义了aboutToAppear,则履行aboutToAppear办法。
  4. 在初次烘托的时候,履行build办法烘托体系组件,假如子组件为自定义组件,则创立自定义组件的实例。在履行build()函数的进程中,结构会调查每个状况变量的读取状况,将保存两个map:
    1. 状况变量 -> UI组件(包括ForEach和if)。
    2. UI组件 -> 此组件的更新函数,即一个lambda办法,作为build()函数的子集,创立对应的UI组件并履行其特点办法,暗示如下。
build() {
  ...
  this.observeComponentCreation(() => {
    Button.create();
  })
  this.observeComponentCreation(() => {
    Text.create();
  })
  ...
}

当运用在后台发动时,此时运用进程并没有毁掉,所以仅需要履行onPageShow。

自定义组件从头烘托

当事情句柄被触发(比方设置了点击事情,即触发点击事情)改动了状况变量时,或许LocalStorage / AppStorage中的特点更改,并导致绑定的状况变量更改其值时:

  1. 结构调查到了变化,将发动从头烘托。
  2. 依据结构持有的两个map(自定义组件的创立和烘托流程中第4步),结构能够知道该状况变量管理了哪些UI组件,以及这些UI组件对应的更新函数。履行这些UI组件的更新函数,完成最小化更新。

自定义组件的删去

假如if组件的分支改动,或许ForEach循环烘托中数组的个数改动,组件将被删去:

  1. 在删去组件之前,将调用其aboutToDisappear生命周期函数,标记着该节点将要被毁掉。ArkUI的节点删去机制是:后端节点直接从组件树上摘下,后端节点被毁掉,对前端节点解引用,前端节点现已没有引用时,将被JS虚拟机废物回收。
  2. 自定义组件和它的变量将被删去,假如其有同步的变量,比方@Link、@Prop、@StorageLink,将从同步源上取消注册。

不主张在生命周期aboutToDisappear内运用async await,假如在生命周期的aboutToDisappear运用异步操作(Promise或许回调办法),自定义组件将被保留在Promise的闭包中,直到回调办法被履行完,这个行为阻挠了自定义组件的废物回收。

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

// Index.ets
import router from '@ohos.router';
@Entry
@Component
struct MyComponent {
  @State showChild: boolean = true;
  // 只要被@Entry装修的组件才能够调用页面的生命周期
  onPageShow() {
    console.info('Index onPageShow');
  }
  // 只要被@Entry装修的组件才能够调用页面的生命周期
  onPageHide() {
    console.info('Index onPageHide');
  }
  // 只要被@Entry装修的组件才能够调用页面的生命周期
  onBackPress() {
    console.info('Index onBackPress');
  }
  // 组件生命周期
  aboutToAppear() {
    console.info('MyComponent aboutToAppear');
  }
  // 组件生命周期
  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').onClick(() => {
        this.showChild = false;
      })
      // push到Page2页面,履行onPageHide
      Button('push to next page')
        .onClick(() => {
          router.pushUrl({ url: 'pages/Page2' });
        })
    }
  }
}
@Component
struct Child {
  @State title: string = 'Hello World';
  // 组件生命周期
  aboutToDisappear() {
    console.info('[lifeCycle] Child aboutToDisappear')
  }
  // 组件生命周期
  aboutToAppear() {
    console.info('[lifeCycle] Child aboutToAppear')
  }
  build() {
    Text(this.title).fontSize(50).onClick(() => {
      this.title = 'Hello ArkUI';
    })
  }
}

以上示例中,Index页面包括两个自定义组件,一个是被@Entry装修的MyComponent,也是页面的进口组件,即页面的根节点;一个是Child,是MyComponent的子组件。只要@Entry装修的节点才能够使页面等级的生命周期办法生效,所以MyComponent中声明晰当时Index页面的页面生命周期函数。MyComponent和其子组件Child也同时也声明晰组件的生命周期函数。

  • 运用冷发动的初始化流程为:MyComponent aboutToAppear –> MyComponent build –> Child aboutToAppear –> Child build –> Child build履行完毕 –> MyComponent build履行完毕 –> 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。

重视公众号:Android老皮!!!欢迎大家来找我讨论交流