@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。
參考資料
頁面和自定義組件生命周期