1# 自定义组件的生命周期 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @seaside_wu1; @huyisuo--> 5<!--Designer: @zhangboren--> 6<!--Tester: @TerryTsao--> 7<!--Adviser: @zhang_yixin13--> 8 9自定义组件的生命周期回调函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。不要在多个窗口复用同一个自定义组件节点,其生命周期可能会紊乱。 10 11>**说明:** 12> 13>- 本模块首批接口从API version 7开始支持,后续版本的新增接口,采用上角标单独标记接口的起始版本。 14>- 允许在生命周期函数中使用Promise和异步回调函数,比如网络资源获取,定时器设置等。 15 16## build 17 18build(): void 19 20build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。 21 22**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 23 24**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 25 26**系统能力:** SystemCapability.ArkUI.ArkUI.Full 27 28## aboutToAppear 29 30aboutToAppear?(): void 31 32aboutToAppear函数在创建自定义组件的新实例后,在其build()函数执行前调用。允许在aboutToAppear函数中改变状态变量,更改将在后续执行build()函数中生效。实现自定义布局的自定义组件的aboutToAppear生命周期在布局过程中触发。 33 34> **说明:** 35> 36> * 在该回调函数内,建议仅执行当前节点组件的初始化逻辑,避免高耗时操作阻塞主线程。对于高耗时操作,推荐采用缓存或异步方案替代。最佳实践请参考[UI组件性能优化-避免在自定义组件的生命周期内执行高耗时操作](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-ui-component-performance-optimization#section18755173594714)。 37> * 在需要频繁创建和销毁组件的场景中,将会频繁调用该回调函数。最佳实践请参考[主线程耗时操作优化指导-组件生命周期回调](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-time-optimization-of-the-main-thread#section418843713435)。 38 39**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 40 41**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 42 43**系统能力:** SystemCapability.ArkUI.ArkUI.Full 44 45## onDidBuild<sup>12+</sup> 46 47onDidBuild?(): void 48 49onDidBuild函数在自定义组件的build()函数执行后调用,开发者可以在这个阶段进行埋点数据上报等不影响实际UI的功能。不建议在onDidBuild函数中更改状态变量、使用animateTo等功能,这可能会导致不稳定的UI表现。 50 51**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 52 53**系统能力:** SystemCapability.ArkUI.ArkUI.Full 54 55## aboutToDisappear 56 57aboutToDisappear?(): void 58 59aboutToDisappear函数在自定义组件析构销毁时执行。不允许在aboutToDisappear函数中改变状态变量,特别是\@Link变量的修改可能会导致应用程序行为不稳定。 60 61> **说明:** 62> 63> 在需要频繁创建和销毁组件的场景中,将会频繁调用该回调函数。最佳实践请参考[主线程耗时操作优化指导-组件生命周期回调](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-time-optimization-of-the-main-thread#section418843713435)。 64 65**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 66 67**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 68 69**系统能力:** SystemCapability.ArkUI.ArkUI.Full 70 71## onPageShow 72 73onPageShow?(): void 74 75router路由页面(仅[\@Entry](../../../../application-dev/ui/state-management/arkts-create-custom-components.md#entry)装饰的自定义组件)每次显示时触发一次,包括路由跳转、应用进入前台等场景。 76 77**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 78 79**系统能力:** SystemCapability.ArkUI.ArkUI.Full 80 81## onPageHide 82 83onPageHide?(): void 84 85router路由页面每次隐藏时触发一次,包括路由跳转、应用进入后台等场景。 86 87> **说明:** 88> 89> 在该回调函数内,建议避免执行高耗时操作阻塞主线程造成卡顿。对于高耗时操作例如相机资源释放,推荐使用异步方案替代。最佳实践请参考[优化应用时延问题-延迟执行资源释放操作](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-application-latency-optimization-cases#section8783201923819)。 90 91**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 92 93**系统能力:** SystemCapability.ArkUI.ArkUI.Full 94 95## onBackPress 96 97onBackPress?(): void | boolean 98 99当用户点击返回按钮时触发(仅router路由页面生效)。返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。 100 101**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 102 103**系统能力:** SystemCapability.ArkUI.ArkUI.Full 104 105**返回值:** 106 107| 类型 | 说明 | 108| ------------------- | --------- | 109| void \| boolean | 返回按钮动作。返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。 | 110 111```ts 112// xxx.ets 113@Entry 114@Component 115struct IndexComponent { 116 @State textColor: Color = Color.Black; 117 118 onPageShow() { 119 this.textColor = Color.Blue; 120 console.info('IndexComponent onPageShow'); 121 } 122 123 onPageHide() { 124 this.textColor = Color.Transparent; 125 console.info('IndexComponent onPageHide'); 126 } 127 128 onBackPress() { 129 this.textColor = Color.Red; 130 console.info('IndexComponent onBackPress'); 131 } 132 133 build() { 134 Column() { 135 Text('Hello World') 136 .fontColor(this.textColor) 137 .fontSize(30) 138 .margin(30) 139 }.width('100%') 140 } 141} 142``` 143 144 145## onNewParam<sup>19+</sup> 146 147onNewParam?(param: ESObject): void 148 149该回调仅生效于由[\@Entry](../../../../application-dev/ui/state-management/arkts-create-custom-components.md#entry)装饰的、作为[router路由](../js-apis-router.md)页面存在的自定义组件。当之前存在于路由栈中的页面,通过[单实例模式](../js-apis-router.md#routermode9)移动到栈顶时触发该回调。 150 151**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。 152 153**系统能力:** SystemCapability.ArkUI.ArkUI.Full 154 155**参数:** 156 157| 参数名 | 类型 | 必填 | 说明 | 158|-------|----------|----------|---------------------------| 159| param | ESObject |是 | 路由跳转时传递到目标页面的数据。| 160 161```ts 162// pages/Index.ets 163import { router } from '@kit.ArkUI'; 164 165export class routerParam { 166 msg: string = '__NA__'; 167 168 constructor(msg: string) { 169 this.msg = msg; 170 } 171} 172 173@Entry 174@Component 175struct Index { 176 aboutToAppear(): void { 177 console.log('onNewParam', 'Index aboutToAppear'); 178 } 179 180 onNewParam(param: ESObject) { 181 console.log('onNewParam', 'Index onNewParam, param: ' + JSON.stringify(param)); 182 } 183 184 build() { 185 Column() { 186 Button('push pageOne Standard') 187 .margin(10) 188 .onClick(() => { 189 this.getUIContext().getRouter().pushUrl({ 190 url: 'pages/PageOne', 191 params: new routerParam('push pageOne Standard') 192 }, router.RouterMode.Standard); 193 }) 194 Button('push pageOne Single') 195 .margin(10) 196 .onClick(() => { 197 this.getUIContext().getRouter().pushUrl({ 198 url: 'pages/PageOne', 199 params: new routerParam('push pageOne Single') 200 }, router.RouterMode.Single) 201 }) 202 } 203 .width('100%') 204 .height('100%') 205 } 206} 207``` 208<!--code_no_check--> 209```ts 210// pages/PageOne.ets 211import { router } from '@kit.ArkUI'; 212import { routerParam } from './Index'; 213 214@Entry 215@Component 216struct PageOne { 217 aboutToAppear(): void { 218 console.log('onNewParam', 'PageOne aboutToAppear'); 219 } 220 221 onNewParam(param: ESObject) { 222 console.log('onNewParam', 'PageOne onNewParam, param: ' + JSON.stringify(param)); 223 } 224 225 build() { 226 Column() { 227 Button('push Index Standard') 228 .margin(10) 229 .onClick(() => { 230 this.getUIContext().getRouter().pushUrl({ 231 url: 'pages/Index', 232 params: new routerParam('push Index Standard') 233 }, router.RouterMode.Standard); 234 }) 235 Button('push Index Single') 236 .margin(10) 237 .onClick(() => { 238 this.getUIContext().getRouter().pushUrl({ 239 url: 'pages/Index', 240 params: new routerParam('push Index Single') 241 }, router.RouterMode.Single) 242 }) 243 } 244 .width('100%') 245 .height('100%') 246 } 247} 248``` 249 250## aboutToReuse<sup>10+</sup> 251 252aboutToReuse?(params: Record\<string, Object | undefined | null>): void 253 254当一个可复用的自定义组件从复用缓存中重新加入到节点树时,触发aboutToReuse生命周期回调,并将组件的构造参数传递给aboutToReuse。 255 256> **说明:** 257> 258> * [避免对@Link/@ObjectLink/@Prop等自动更新的状态变量,在aboutToReuse()中重复赋值](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-component-reuse#section7441712174414)。 259> * 在滑动场景中,使用组件复用通常需要用该回调函数去更新组件的状态变量,因此在该回调函数中应避免耗时操作,否则会导致丢帧卡顿。最佳实践请参考[主线程耗时操作优化指导-组件复用回调](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-time-optimization-of-the-main-thread#section20815336174316)。 260 261**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 262 263**系统能力:** SystemCapability.ArkUI.ArkUI.Full 264 265**参数:** 266 267| 参数名 | 类型 | 必填 | 说明 | 268|--------|-------------------------------------------|-----|---------------------| 269| params | Record\<string, Object \| undefined \| null> | 是 | 自定义组件的构造参数。| 270 271```ts 272// xxx.ets 273export class Message { 274 value: string | undefined; 275 276 constructor(value: string) { 277 this.value = value 278 } 279} 280 281@Entry 282@Component 283struct Index { 284 @State switch: boolean = true 285 286 build() { 287 Column() { 288 Button('Hello World') 289 .fontSize(50) 290 .fontWeight(FontWeight.Bold) 291 .onClick(() => { 292 this.switch = !this.switch 293 }) 294 if (this.switch) { 295 Child({ message: new Message('Child') }) 296 } 297 } 298 .height("100%") 299 .width('100%') 300 } 301} 302 303@Reusable 304@Component 305struct Child { 306 @State message: Message = new Message('AboutToReuse'); 307 308 aboutToReuse(params: Record<string, ESObject>) { 309 console.info("Recycle Child") 310 this.message = params.message as Message 311 } 312 313 build() { 314 Column() { 315 Text(this.message.value) 316 .fontSize(20) 317 } 318 .borderWidth(2) 319 .height(100) 320 } 321} 322``` 323 324## aboutToReuse<sup>18+</sup> 325 326aboutToReuse?(): void 327 328当一个状态管理V2的可复用自定义组件从复用池被取出重新加入到节点树时,触发aboutToReuse生命周期回调。 329 330详细内容请参考[\@ReusableV2](../../../ui/state-management/arkts-new-reusableV2.md)。 331 332**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 333 334**系统能力:** SystemCapability.ArkUI.ArkUI.Full 335 336```ts 337@Entry 338@ComponentV2 339struct Index { 340 @Local condition: boolean = true; 341 build() { 342 Column() { 343 Button('回收/复用').onClick(()=>{this.condition=!this.condition;}) // 点击切换回收/复用状态 344 if (this.condition) { 345 ReusableV2Component() 346 } 347 } 348 } 349} 350@ReusableV2 351@ComponentV2 352struct ReusableV2Component { 353 @Local message: string = 'Hello World'; 354 aboutToReuse() { 355 console.log('ReusableV2Component aboutToReuse'); // 复用时被调用 356 } 357 build() { 358 Column() { 359 Text(this.message) 360 } 361 } 362} 363``` 364 365 366## aboutToRecycle<sup>10+</sup> 367 368aboutToRecycle?(): void 369 370组件的生命周期回调,在可复用组件从组件树上被加入到复用缓存之前调用。 371 372**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 373 374**系统能力:** SystemCapability.ArkUI.ArkUI.Full 375 376```ts 377// xxx.ets 378export class Message { 379 value: string | undefined; 380 381 constructor(value: string) { 382 this.value = value; 383 } 384} 385 386@Entry 387@Component 388struct Index { 389 @State switch: boolean = true; 390 391 build() { 392 Column() { 393 Button('Hello World') 394 .fontSize(50) 395 .fontWeight(FontWeight.Bold) 396 .onClick(() => { 397 this.switch = !this.switch; 398 }) 399 if (this.switch) { 400 Child({ message: new Message('Child') }) 401 } 402 } 403 .height("100%") 404 .width('100%') 405 } 406} 407 408@Reusable 409@Component 410struct Child { 411 @State message: Message = new Message('AboutToReuse'); 412 413 aboutToReuse(params: Record<string, ESObject>) { 414 console.info("Reuse Child"); 415 this.message = params.message as Message; 416 } 417 418 aboutToRecycle() { 419 //这里可以释放比较占内存的内容或其他非必要资源引用,避免一直占用内存,引发内存泄漏 420 console.info("Recycle Child,child进入复用池中"); 421 } 422 423 build() { 424 Column() { 425 Text(this.message.value) 426 .fontSize(20) 427 } 428 .borderWidth(2) 429 .height(100) 430 } 431} 432``` 433 434## onWillApplyTheme<sup>12+</sup> 435 436onWillApplyTheme?(theme: Theme): void 437 438onWillApplyTheme函数用于获取当前组件上下文的Theme对象,在创建自定义组件的新实例后,在执行其build()函数之前执行。允许在onWillApplyTheme函数中改变状态变量,更改将在后续执行build()函数中生效。 439 440> **说明:** 441> 442> 从API version 18开始,该接口支持在状态管理V2组件中使用。 443 444**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 445 446**系统能力:** SystemCapability.ArkUI.ArkUI.Full 447 448**参数:** 449 450| 参数名 | 类型 | 必填 | 说明 | 451|--------|------------------------------------------|------------|-------------------------| 452| theme | [Theme](#theme12) | 是 | 自定义组件当前生效的Theme对象。| 453 454## Theme<sup>12+</sup> 455 456type Theme = Theme 457 458**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 459 460**系统能力:** SystemCapability.ArkUI.ArkUI.Full 461 462| 类型 | 说明 | 463| --------------------------------------------------------- | ----------------------- | 464| [Theme](../js-apis-arkui-theme.md#theme) | 自定义组件当前生效的Theme对象。 | 465 466V1: 467 468```ts 469// xxx.ets 470import { CustomTheme, CustomColors, Theme, ThemeControl } from '@kit.ArkUI'; 471 472class BlueColors implements CustomColors { 473 fontPrimary = Color.White; 474 backgroundPrimary = Color.Blue; 475 brand = Color.Blue; //品牌色 476} 477 478class PageCustomTheme implements CustomTheme { 479 colors?: CustomColors; 480 481 constructor(colors: CustomColors) { 482 this.colors = colors; 483 } 484} 485const BlueColorsTheme = new PageCustomTheme(new BlueColors()); 486// setDefaultTheme应该在应用入口页面调用或者在Ability中调用。 487ThemeControl.setDefaultTheme(BlueColorsTheme); 488 489@Entry 490@Component 491struct IndexComponent { 492 @State textColor: ResourceColor = $r('sys.color.font_primary'); 493 @State columBgColor: ResourceColor = $r('sys.color.background_primary'); 494 495 // onWillApplyTheme中可获取当前组件上下文的Theme对象。此处在onWillApplyTheme中将状态变量textColor、columBgColor,赋值为当前使用的Theme对象(BlueColorsTheme)中的配色。 496 onWillApplyTheme(theme: Theme) { 497 this.textColor = theme.colors.fontPrimary; 498 this.columBgColor = theme.colors.backgroundPrimary; 499 console.info('IndexComponent onWillApplyTheme'); 500 } 501 502 build() { 503 Column() { 504 // 组件初始值配色样式 505 Column() { 506 Text('Hello World') 507 .fontColor($r('sys.color.font_primary')) 508 .fontSize(30) 509 } 510 .width('100%') 511 .height('25%') 512 .borderRadius('10vp') 513 .backgroundColor($r('sys.color.background_primary')) 514 515 // 组件颜色生效为onWillApplyTheme中配置颜色。 516 Column() { 517 Text('onWillApplyTheme') 518 .fontColor(this.textColor) 519 .fontSize(30) 520 Text('Hello World') 521 .fontColor(this.textColor) 522 .fontSize(30) 523 } 524 .width('100%') 525 .height('25%') 526 .borderRadius('10vp') 527 .backgroundColor(this.columBgColor) 528 } 529 .padding('16vp') 530 .backgroundColor('#dcdcdc') 531 .width('100%') 532 .height('100%') 533 } 534} 535``` 536 537 538V2: 539 540```ts 541import { CustomTheme, CustomColors, Theme, ThemeControl } from '@kit.ArkUI'; 542 543class BlueColors implements CustomColors { 544 fontPrimary = Color.White; 545 backgroundPrimary = Color.Blue; 546 brand = Color.Blue; //品牌色 547} 548 549class PageCustomTheme implements CustomTheme { 550 colors?: CustomColors; 551 552 constructor(colors: CustomColors) { 553 this.colors = colors; 554 } 555} 556 557const BlueColorsTheme = new PageCustomTheme(new BlueColors()); 558// setDefaultTheme应该在应用入口页面调用或者在Ability中调用。 559ThemeControl.setDefaultTheme(BlueColorsTheme); 560 561@Entry 562@ComponentV2 563struct IndexComponent { 564 @Local textColor: ResourceColor = $r('sys.color.font_primary'); 565 @Local columBgColor: ResourceColor = $r('sys.color.background_primary'); 566 567 // onWillApplyTheme中可获取当前组件上下文的Theme对象。此处在onWillApplyTheme中将状态变量textColor、columBgColor,赋值为当前使用的Theme对象(BlueColorsTheme)中的配色。 568 onWillApplyTheme(theme: Theme) { 569 this.textColor = theme.colors.fontPrimary; 570 this.columBgColor = theme.colors.backgroundPrimary; 571 console.info('IndexComponent onWillApplyTheme'); 572 } 573 574 build() { 575 Column() { 576 // 组件初始值配色样式 577 Column() { 578 Text('Hello World') 579 .fontColor($r('sys.color.font_primary')) 580 .fontSize(30) 581 } 582 .width('100%') 583 .height('25%') 584 .borderRadius('10vp') 585 .backgroundColor($r('sys.color.background_primary')) 586 587 // 组件颜色生效为onWillApplyTheme中配置颜色。 588 Column() { 589 Text('onWillApplyTheme') 590 .fontColor(this.textColor) 591 .fontSize(30) 592 Text('Hello World') 593 .fontColor(this.textColor) 594 .fontSize(30) 595 } 596 .width('100%') 597 .height('25%') 598 .borderRadius('10vp') 599 .backgroundColor(this.columBgColor) 600 } 601 .padding('16vp') 602 .backgroundColor('#dcdcdc') 603 .width('100%') 604 .height('100%') 605 } 606} 607``` 608 609 610 611## pageTransition<sup>9+</sup> 612 613pageTransition?(): void 614 615进入此页面或移动到其他页面时实现动画。 616 617**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 618 619**系统能力:** SystemCapability.ArkUI.ArkUI.Full