在開始之前惠奸,我們先明確自定義組件和頁面的關系:
- 自定義組件:@Component裝飾的UI單元梅誓,可以組合多個系統(tǒng)組件實現UI的復用,可以調用組件的生命周期佛南。
- 頁面:即應用的UI頁面梗掰。可以由一個或者多個自定義組件組成嗅回,@Entry裝飾的自定義組件為頁面的入口組件及穗,即頁面的根節(jié)點,一個頁面有且僅能有一個@Entry绵载。只有被@Entry裝飾的組件才可以調用頁面的生命周期埂陆。
頁面生命周期,即被@Entry裝飾的組件生命周期娃豹,提供以下生命周期接口:
- onPageShow:頁面每次顯示時觸發(fā)一次焚虱,包括路由過程、應用進入前臺等場景懂版。
- onPageHide:頁面每次隱藏時觸發(fā)一次鹃栽,包括路由過程躯畴、應用進入后臺等場景民鼓。
- onBackPress:當用戶點擊返回按鈕時觸發(fā)薇芝。
組件生命周期,即一般用@Component裝飾的自定義組件的生命周期丰嘉,提供以下生命周期接口:
- aboutToAppear:組件即將出現時回調該接口夯到,具體時機為在創(chuàng)建自定義組件的新實例后,在執(zhí)行其build()函數之前執(zhí)行饮亏。
- onDidBuild:組件build()函數執(zhí)行完成之后回調該接口耍贾,不建議在onDidBuild函數中更改狀態(tài)變量、使用animateTo等功能克滴,這可能會導致不穩(wěn)定的UI表現逼争。
- aboutToDisappear:aboutToDisappear函數在自定義組件析構銷毀之前執(zhí)行。不允許在aboutToDisappear函數中改變狀態(tài)變量劝赔,特別是@Link變量的修改可能會導致應用程序行為不穩(wěn)定誓焦。
生命周期流程如下圖所示,下圖展示的是被@Entry裝飾的組件(頁面)生命周期着帽。
0000000000011111111.20241105122222.86175125760562943871986980520675.png
以下示例展示了生命周期的調用時機:
// Index.ets
import { router } from '@kit.ArkUI';
@Entry
@Component
struct 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赫粥,創(chuàng)建Child子組件,執(zhí)行Child aboutToAppear
if (this.showChild) {
Child()
}
// this.showChild為false予借,刪除Child子組件越平,執(zhí)行Child aboutToDisappear
Button('delete Child')
.margin(20)
.backgroundColor(this.btnColor)
.onClick(() => {
this.showChild = false;
})
// push到page頁面,執(zhí)行onPageHide
Button('push to next page')
.onClick(() => {
router.pushUrl({ url: 'pages/page' });
})
}
}
}
@Component
struct 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
@Component
struct 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,也是頁面的入口組件瀑粥,即頁面的根節(jié)點挣跋;一個是Child,是MyComponent的子組件狞换。只有@Entry裝飾的節(jié)點才可以使頁面級別的生命周期方法生效避咆,因此在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組件樊销,會執(zhí)行Child aboutToDisappear方法。
- 點擊“push to next page”,調用router.pushUrl接口现柠,跳轉到另外一個頁面,當前Index頁面隱藏弛矛,執(zhí)行頁面生命周期Index onPageHide够吩。此處調用的是router.pushUrl接口,Index頁面被隱藏丈氓,并沒有銷毀周循,所以只調用onPageHide。跳轉到新頁面后万俗,執(zhí)行初始化新頁面的生命周期的流程湾笛。
- 如果調用的是router.replaceUrl,則當前Index頁面被銷毀闰歪,執(zhí)行的生命周期流程將變?yōu)椋篒ndex onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear嚎研。上文已經提到,組件的銷毀是從組件樹上直接摘下子樹库倘,所以先調用父組件的aboutToDisappear临扮,再調用子組件的aboutToDisappear,然后執(zhí)行初始化新頁面的生命周期流程教翩。
- 點擊返回按鈕杆勇,觸發(fā)頁面生命周期Index onBackPress,且觸發(fā)返回一個頁面后會導致當前Index頁面被銷毀饱亿。
- 最小化應用或者應用進入后臺蚜退,觸發(fā)Index onPageHide。當前Index頁面沒有被銷毀彪笼,所以并不會執(zhí)行組件的aboutToDisappear钻注。應用回到前臺,執(zhí)行Index onPageShow杰扫。
- 退出應用队寇,執(zhí)行Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。