HarmonyOS-ArkUI Navigation (導航組件)-第一部分

導航組件主要實現頁面間以及組件內部的界面跳轉,支持在不同的組件間進行參數的傳遞,提供靈活的跳轉棧操作,從而便捷的實現對不同頁面的訪問和復用。

我們之前學習過Tabs組件,這個組件里面也有支持跳轉的方式,Navigation與Tabs最主要的區別就在于,Navigation里面含有一個跳轉棧,且使用方式比Tabs更為復雜。這個相當于Android中Fragment的Navigation,異曲同工。下文中我們將會習得

  • 導航組件的顯示模式
  • 導航組件的路由操作
  • 子頁面管理
  • 跨包跳轉
  • 跳轉動效

想要支持Navigation的棧式維護和跳轉,需要在頁面的build函數下,將Navigation作為根節點,也就是視圖的根容器!要不然不行。并且,其跳轉到的頁面的根容器,一定要是NavDestination,否則即使跳轉過去了,您的頁面也是沒有被渲染的,Navigation組件本身也提供了布局的結構,也可以供您進行設置。

Navigation體系的界面有兩大部分構成

  • 主頁, 主頁是所有導航的源頭處,引發的第一個導航。我們的路由棧(NavPathStack也是在這個入口處進行設置,并由子頁一層一層傳遞始終能夠拿到這個句柄,來進行導航的。
  • 子頁, 就是被導航的頁面。 子頁也可以導航到其他的頁面,主要就是得拿到那個唯一的路由棧(NavPathStack

主頁與子頁之間的導航器,可以配合由 Provide 和 Consume 兩個裝飾器來進行傳遞,之后有案例,可以在代碼中注意一下使用方式。


主頁與子頁內容構成圖

未加任何復雜操作的主頁(主要展示標題,菜單欄,工具欄的展示方式)

@Entry
@Component
struct NavigatePage {@State message: string = 'Hello World';@State TooTmp:ToolbarItem = {value: 'func', icon: $r('app.media.ic_ok')}// 用這個@Provide裝飾器裝飾的變量,可以傳遞給子組件@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()build() {Column(){Navigation(this.pageInfos) {}//設置為分欄模式.mode(NavigationMode.Stack)//設置頂部標題.title("主標題")// 設置頂部菜單欄.menus([{value: "菜單1", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單2", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單3", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單4", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單5", icon: $r('app.media.ic_icon'), action: () => {}}])//設置底部工具欄.toolbarConfiguration([this.TooTmp, this.TooTmp, this.TooTmp])}.height('100%').width('100%').backgroundColor('#F1F3F5')}
}

界面設置基礎

設置頁面顯示模式

在上文中的代碼中,有一個屬性叫 mode, 它是用來設置頁面模式的。 頁面模式總共分為三種

  • Stack:單欄
  • Split: 分欄
  • Auto:自適應

Split模式

上圖中我們設置的主頁面是 Stack模式,為單欄的效果。其實也可以設置分欄模式,其值設置為 Split即可。

下圖為設置為分欄模式的樣子,好讓大家有個印象。

@Entry
@Component
struct NavigatePage {@State message: string = 'Hello World';@State TooTmp:ToolbarItem = {value: 'func', icon: $r('app.media.ic_ok')}// 用這個@Provide裝飾器裝飾的變量,可以傳遞給子組件@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()build() {Column(){Navigation(this.pageInfos) {}//設置為分欄模式.mode(NavigationMode.Split)//設置頂部標題.title("主標題")...省略其他設置代碼...}.height('100%').width('100%').backgroundColor('#F1F3F5')}
}

Auto模式

Auto模式是讓導航頁面自己計算大小,屏幕寬就雙列展示,不寬就單列顯示。

設置標題模式

如果您寫了一個Navigation組件,沒有設置title的情況下這個title是不會顯示的。但是如果設置了,從上圖中你也看到了,這個標題是不是有些,太大了🥶。Navigetion組件可以通過titleMode屬性設置標題欄的模式。titleMode屬性的值為:

  • Free:默認值,我試著是和Full是一樣的效果,官網API沒看出來啥區別。遇見區別之后再補修一下文章。
  • Full:強調型標題欄,用于以及界面需要圖書標題的場景.
  • Mini:普通標題欄模式,用于一級頁面不需要突出標題的場景。

Full模式

mini模式

設置菜單欄

菜單欄的展示行為

菜單欄位置是下方紅圈中區域。

當設備處于豎屏模式下,最多展示3個圖標,為橫屏模式下,最多展示5個圖標。這里需要注意的是,這個展示的情況是與設備所處的橫豎屏狀態有關。

設置菜單欄

菜單欄通過Navigation組件的menus屬性進行設置。其聲明格式如下:

menus(value: Array<NavigationMenuItem> | CustomBuilder): NavigationAttribute;

其參數可以使一個數組,也可以是一個自定義構建函數

采用數組設置menus
 build() {Column(){Navigation(this.pageInfos) {TextInput({placeholder: 'search'}).width("90%").margin({top: 20,}).backgroundColor('#FFFFFF')List({space: 20}) {ForEach(this.arr, (item:number) => {ListItem() {Text("Page" + item).width("100%").height(72).backgroundColor('#FFFFFF').borderRadius(24).fontSize(16).fontWeight(500).textAlign(TextAlign.Center).onClick(() => {this.pageInfos.pushPath({name: "NavDestinationTitle" + item})})}}, (item:number) => item.toString())}.width('90%').margin({top: 12})}//設置為分欄模式.mode(NavigationMode.Stack).navDestination(this.pageMap)//設置頂部標題.title("主標題").titleMode(NavigationTitleMode.Full)// 設置頂部菜單欄.menus([{value: "菜單1", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單2", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單3", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單4", icon: $r('app.media.ic_icon'), action: () => {}},{value: "菜單5", icon: $r('app.media.ic_icon'), action: () => {}}])//設置底部工具欄.toolbarConfiguration([this.TooTmp, this.TooTmp, this.TooTmp])}.height('100%').width('100%').backgroundColor('#F1F3F5')}
采用自定義構建函數設置menus
@Builder myMenus(){Row(){Text('菜單1')Text('菜單2')Text('菜單3')Text('菜單4')Text('菜單5')}}build() {Column(){Navigation(this.pageInfos) {TextInput({placeholder: 'search'}).width("90%").margin({top: 20,}).backgroundColor('#FFFFFF')List({space: 20}) {ForEach(this.arr, (item:number) => {ListItem() {Text("Page" + item).width("100%").height(72).backgroundColor('#FFFFFF').borderRadius(24).fontSize(16).fontWeight(500).textAlign(TextAlign.Center).onClick(() => {this.pageInfos.pushPath({name: "NavDestinationTitle" + item})})}}, (item:number) => item.toString())}.width('90%').margin({top: 12})}//設置為分欄模式.mode(NavigationMode.Stack).navDestination(this.pageMap)//設置頂部標題.title("主標題").titleMode(NavigationTitleMode.Full)// 設置頂部菜單欄.menus(this.myMenus)//設置底部工具欄.toolbarConfiguration([this.TooTmp, this.TooTmp, this.TooTmp])}.height('100%').width('100%').backgroundColor('#F1F3F5')}

設置工具欄

工具欄是下圖中所示的位置,如果不進行設置,就不會展示。工具欄的設置由toolBarConfiguration屬性進行設置。

toolBarConfiguration的聲明如下文所示:

toolbarConfiguration(value: Array<ToolbarItem> | CustomBuilder, options?: NavigationToolbarOptions): NavigationAttribute;

其參數可以是一個數組,也可以是一個自定義構建函數。具體寫法與menus非常類似。

@State TooTmp:ToolbarItem = {value: 'func', icon: $r('app.media.ic_ok')}build() {Column(){Navigation(this.pageInfos) {TextInput({placeholder: 'search'}).width("90%").margin({top: 20,}).backgroundColor('#FFFFFF')List({space: 20}) {ForEach(this.arr, (item:number) => {ListItem() {Text("Page" + item).width("100%").height(72).backgroundColor('#FFFFFF').borderRadius(24).fontSize(16).fontWeight(500).textAlign(TextAlign.Center).onClick(() => {this.pageInfos.pushPath({name: "NavDestinationTitle" + item})})}}, (item:number) => item.toString())}.width('90%').margin({top: 12})}//設置為分欄模式.mode(NavigationMode.Stack).navDestination(this.pageMap)//設置頂部標題.title("主標題").titleMode(NavigationTitleMode.Full)// 設置頂部菜單欄.menus(this.myMenus)//設置底部工具欄.toolbarConfiguration([this.TooTmp, this.TooTmp, this.TooTmp])}.height('100%').width('100%').backgroundColor('#F1F3F5')}

路由操作

我們在Navitgation構建的時候,傳遞了一個參數。如圖所示:

上圖中NavPathStack是我們這個小節學習的重點,這個對象必須在Navigation構建的時候傳入。Navigation整個體系下所有和路由相關的操作都是由NavPathStack提供的方法進行,這個對象主要就是用于頁面的管理。其功能主要如下:

  • 頁面跳轉
  • 頁面返回
  • 頁面替換
  • 頁面刪除
  • 參數獲取,數據傳遞。
  • 路由攔截
  • ...

我們在頁面進行操作之前,是有必要稍微了解下,導航組件完成完整功能的構成成分。以及與我們之前寫的代碼的對應部分(紅色虛線)。好在心里有個藍圖。


頁面跳轉的一切基礎,就是首先Navigation對應的頁面棧NavPathStack您得提供。這個對象會在Navigation初始化的時候被傳入,您可以用ArkUI中已經提供的類,也可以自己寫一個子類,創建一個對象實例,傳入即可。

@Entry
@Component
struct Index {// 創建一個頁面棧對象并傳入NavigationpageStack: NavPathStack = new NavPathStack()build() {Navigation(this.pageStack) {}.title('主標題')}
}

頁面跳轉

NavPathStack通過Push相關的接口去實現頁面跳轉的功能,主要分為三類

  • 普通跳轉
  • 帶返回回調的跳轉
  • 帶錯誤碼的跳轉,跳轉結束會觸發異步回調,返回錯誤碼信息。

普通跳轉

this.pageInfos.pushPath({name: "NavDestinationTitle" + item, param: ''})
this.pageInfos.pushPathByName("NavDestinationTitle" + item, '')

帶返回回調的跳轉

跳轉時可以添加onPop回調,能在頁面出棧時獲取返回信息。不知道為什么我自己寫的不會返回。這個我調試的表現跟官網不一樣。

this.pageInfos.pushPathByName("NavDestinationTitle" + item, '', (popInfo) => {hilog.info(DOMAIN_NAVIGATE, TAG, 'Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result))
})

帶錯誤碼的跳轉

跳轉結束觸發異步回調,返回錯誤碼信息。當被導航的界面打開的時候就會回調success

this.pageInfos.pushDestination({name: "NavDestinationTitle" + item, param: ''}).catch((error: BusinessError) => {hilog.error(DOMAIN_NAVIGATE, TAG, 'error Name= ' + error.name + " code=" + error.code + " message=" + error.message + " data=" + error.data)}).then(()=> {hilog.info(DOMAIN_NAVIGATE, TAG, "open success")})

或者這樣寫也可以

this.pageInfos.pushDestinationByName( "NavDestinationTitle" + item,  '').catch((error: BusinessError) => {hilog.error(DOMAIN_NAVIGATE, TAG, 'error Name= ' + error.name + " code=" + error.code + " message=" + error.message + " data=" + error.data)}).then(()=> {hilog.info(DOMAIN_NAVIGATE, TAG, "open success")})
})

頁面返回

NavPathStack通過pop相關接口去實現頁面返回功能。


@Component
export struct PageOne {@State message: string = 'PageOne';@Consume('pageInfos') pageStack: NavPathStackbuild() {// 注意這里必須加上NavDestination方法,否則導航有效果但是界面展示不出來.NavDestination(){RelativeContainer() {Text(this.message + ' content').id('PageOne').fontSize($r('app.float.page_text_font_size')).fontWeight(FontWeight.Bold).alignRules({center: { anchor: '__container__', align: VerticalAlign.Center },middle: { anchor: '__container__', align: HorizontalAlign.Center }}).onClick(() => {this.message = 'Welcome';})}.height('100%').width('100%').backgroundColor(Color.Red)}.title(this.message).onBackPressed(()=>{const popInfo = this.pageStack.pop(); //彈出棧頂元素console.log('pop' + '返回值' + JSON.stringify(popInfo))return true;})}
}

另外還有幾個其他的接口

// 返回到上一頁
this.pageStack.pop()
//返回到上一個pageOne頁
this.pageStack.popToName('pageOne')
// 返回到索引為1的頁面
this.pageStack.popToIndex(1)
// 返回到根首頁,也就是主頁
this.pageStack.clear()

頁面替換

NavPathStack通過Replace相關接口去實現頁面的替換功能。

.onBackPressed(()=>{// 注意此時的name,名稱要是在RouterMap中注冊的那些文字,否則找不到要替換哪一個的const info = this.pageStack.replacePath({name: "NavDestinationTitle1", param: ""})console.log('pop' + '返回值' + JSON.stringify(info))return true;})
// 將棧頂頁面替換為PageOne
this.pageStack.replacePath({ name: "PageOne", param: "PageOne Param" })
this.pageStack.replacePathByName("PageOne", "PageOne Param")
// 帶錯誤碼的替換,跳轉結束會觸發異步回調,返回錯誤碼信息
this.pageStack.replaceDestination({name: "PageOne", param: "PageOne Param"}).catch((error: BusinessError) => {console.error(`Replace destination failed, error code = ${error.code}, error.message = ${error.message}.`);}).then(() => {console.info('Replace destination succeed.');})

頁面刪除

NavPathStack通過Remove相關接口實現頁面的刪除。

// 刪除棧中name為PageOne的所有頁面
this.pageStack.removeByName("PageOne")
// 刪除指定索引的頁面
this.pageStack.removeByIndexes([1,3,5])
// 刪除指定id的頁面
this.pageStack.removeByNavDestinationId("1");

移動頁面

移動頁面指的是,移動棧中的某指定頁面到棧頂的位置。

// 移動棧中name為PageOne的頁面到棧頂
this.pageStack.moveToTop("PageOne");
// 移動棧中索引為1的頁面到棧頂
this.pageStack.moveIndexToTop(1);

獲取參數

NavPathStack中的獲取參數是比較有意思的,因為它可以按照頁面獲取參數,比如您現在在pageTwo中,也是可以搞到pogeOne中的參數的。這個就會數據中心的實現提供了很多的便利。

NavPathStack提供了一系列get操作去獲取參數。


// 獲取棧中所有頁面name集合
this.pageStack.getAllPathName()
// 獲取索引為1的頁面參數
this.pageStack.getParamByIndex(1)
// 獲取PageOne頁面的參數
this.pageStack.getParamByName("PageOne")
// 獲取PageOne頁面的索引集合
this.pageStack.getIndexByName("PageOne")

路由攔截

NavPathStack提供了setInterception方法,用于設置Navigation跳轉的攔截回調, 該方法需要傳入一個NavigationInterception對象,該對象包含三個參數。

willShow

頁面跳轉前回調,此時可以修改操作棧中的行為

didShow

頁面跳轉后回調,此時不可以修改操作棧中的行為。

modeChange

單雙欄顯示發生變化時回調,主要是橫豎屏切換的時候。

下方代碼為,當跳轉到pageTwo的時候,我們攔截,使其轉向pageOne。

aboutToAppear(): void {this.pageInfos.setInterception({/*** willShow需要格外注意的是, 當A跳轉至B, B又跳轉至A的時候, A的willShow也會被調用的,因為A的確是即將被展示了.* 我們在理邏輯的時候,除了注意將要跳轉的界面,也要注意將要返回的界面.*/willShow: (from: NavDestinationContext | NavBar, to: NavDestinationContext | NavBar, operation: NavigationOperation, isAnimated: boolean) => {// 當為導航主頁的時候,這里的to是一個string類型,內容為 "navBar"if (typeof to === 'string') {let toStr:string = to as stringhilog.warn(DOMAIN_NAVIGATE, TAG, 'navigation home page! to=' + to)return}// 當為子導航頁的時候,這里的to是NavDestinationContext類型// 修改操作棧,發現是PageTwo的跳轉,就改成PageOnelet target: NavDestinationContext = to as NavDestinationContexthilog.info(DOMAIN_NAVIGATE, TAG, 'common page! to=' + JSON.stringify(target))if (target.pathInfo.name === 'NavDestinationTitle2') {target.pathStack.pop()target.pathStack.pushPath({name: 'NavDestinationTitle1'})}},didShow: (from: NavDestinationContext | NavBar, to: NavDestinationContext | NavBar, operation: NavigationOperation, isAnimated: boolean) => {hilog.debug(DOMAIN_NAVIGATE, TAG, "didShow callback")},modeChange: (mode: NavigationMode) => {hilog.debug(DOMAIN_NAVIGATE, TAG, "modeChange callback")}})}

子頁面

子頁面對應的是NavDestination組件,是Navigation體系中子頁面部分的根容器,用于承載子頁面的一些特殊屬性和生命周期等。它可以設置獨立的菜單欄和標題欄等屬性,這類屬性的設置方法與Navigation是一致的。

NavDestination的頁面顯示模式

NavDestination設置頁面顯示模式的屬性,也叫 mode。通過設置mode屬性,可以滿足不同頁面的訴求。

頁面顯示類型

  • 標準類型:NavDestination的默認顯示模式就是標準類型,此時mode = NavDestinationMode.STANDARD 。 標準類型的子頁面生命周期跟隨在NavPathStack頁面棧中的位置變化而變化。
  • 彈窗類型:NavDestination設置mode為 NavDestinationMode.DIALOG類型時,代表當前子頁面是彈窗類型,此時整個NavDestination默認透明顯示,并且它的消失和出現并不會影響下層標準類型的顯示和生命周期,兩者是可以同時顯示的。 彈窗默認動效是從低向上平滑彈出

@Preview
@Component
export struct PageFourDialog {@Consume('pageInfos') pageStack: NavPathStackbuild() {NavDestination(){RelativeContainer() {RelativeContainer(){Text("這是一個彈窗").id('title').fontSize(20).alignRules({top: {anchor: '__container__', align: VerticalAlign.Top},start: {anchor: '__container__', align: HorizontalAlign.Start},end: {anchor: '__container__', align: HorizontalAlign.End}}).margin({top: 80}).fontWeight(FontWeight.Bold).textAlign(TextAlign.Center)Button("退出").fontSize(18).alignRules({top: {anchor: 'title', align: VerticalAlign.Bottom},start: {anchor: '__container__', align: HorizontalAlign.Start},end: {anchor: '__container__', align: HorizontalAlign.End}}).width('30%').margin({top: 50}).onClick(()=>{this.pageStack.pop()})}.alignRules({top: {anchor: '__container__', align: VerticalAlign.Top},start: {anchor: '__container__', align: HorizontalAlign.Start},end: {anchor: '__container__', align: HorizontalAlign.End},bottom: {anchor: '__container__', align: VerticalAlign.Bottom}}).height('30%').width('80%').backgroundColor(Color.White).borderRadius(20)}.height('100%').width('100%').borderRadius(20)}.hideTitleBar(true) //關掉標題欄區域.backgroundColor('rgba(0, 0, 0, 0.3)').mode(NavDestinationMode.DIALOG)  //指定為彈窗模式}
}

頁面生命周期

頁面監聽和查詢

為了方便組件與頁面解耦,在NavDestination子頁面定義的自定義組件可以通過全局方法監聽或查詢到頁面的一些狀態信息。

頁面信息查詢

自定義組件提供了quertNavDestinationInfo方法。可以在NavDestination內部查詢到當前頁面的信息,返回值是NavDestination,如果查詢不到則返回undefined。

import { JSON } from "@kit.ArkTS"@Preview
@Component
export struct PageFourDialog {@Consume('pageInfos') pageStack: NavPathStackbuild() {NavDestination(){RelativeContainer() {RelativeContainer(){Text("這是一個彈窗").id('title').fontSize(20).alignRules({top: {anchor: '__container__', align: VerticalAlign.Top},start: {anchor: '__container__', align: HorizontalAlign.Start},end: {anchor: '__container__', align: HorizontalAlign.End}}).margin({top: 80}).fontWeight(FontWeight.Bold).textAlign(TextAlign.Center)BackButton()}.alignRules({top: {anchor: '__container__', align: VerticalAlign.Top},start: {anchor: '__container__', align: HorizontalAlign.Start},end: {anchor: '__container__', align: HorizontalAlign.End},bottom: {anchor: '__container__', align: VerticalAlign.Bottom}}).height('30%').width('80%').backgroundColor(Color.White).borderRadius(20)}.height('100%').width('100%').borderRadius(20)}.hideTitleBar(true) //關掉標題欄區域.backgroundColor('rgba(0, 0, 0, 0.3)').mode(NavDestinationMode.DIALOG)  //指定為彈窗模式}
}@Component
struct BackButton{@Consume('pageInfos') pageStack: NavPathStacknavDInfo:NavDestinationInfo | undefined;aboutToAppear(): void {// navDInfo = {"navigationId":"","name":"NavDestinationTitle4","state":4,// "index":0,"param":"NavDestinationTitle4","navDestinationId":"0"}this.navDInfo = this.queryNavDestinationInfo();console.log("navDInfo = " + JSON.stringify(this.navDInfo))}build() {Button("退出").fontSize(18).alignRules({top: {anchor: 'title', align: VerticalAlign.Bottom},start: {anchor: '__container__', align: HorizontalAlign.Start},end: {anchor: '__container__', align: HorizontalAlign.End}}).width('30%').margin({top: 50}).onClick(()=>{this.pageStack.pop()})}
}

頁面狀態監聽

通過observer.on('navDestinationUpdate')提供的注冊接口可以注冊NavDestination生命周期變化的監聽,使用方式如下:

import { JSON } from "@kit.ArkTS"
import { uiObserver } from "@kit.ArkUI"@Preview
@Component
export struct PageFourDialog {@Consume('pageInfos') pageStack: NavPathStackaboutToAppear(): void {uiObserver.on('navDestinationUpdate', (data: NavDestinationInfo)=>{console.log("navDestinationUpdate data=" + JSON.stringify(data))})}
...

監聽切換頁面的行為

aboutToAppear(): void {uiObserver.on('navDestinationUpdate', (data: NavDestinationInfo)=>{console.log("navDestinationUpdate data=" + JSON.stringify(data))})// 頁面切換狀態回調uiObserver.on('navDestinationSwitch', this.getUIContext(), (data:uiObserver.NavDestinationSwitchInfo) =>{console.log('navDestinationSwitch data=' + JSON.stringify(data))})}

頁面轉場

Navigation默認提供了頁面的轉場動畫,通過頁面棧操作時會觸發不同的轉場效果。如果不想要,可以設置關閉系統轉場動畫,同時您也可以進行自定義轉場,以及共享元素轉場的能力。

關閉轉場

關閉轉場有關閉全局轉場和開啟子頁面時臨時設置關閉轉場動畫。首先將關閉全局的轉場。用到了NavPathStack的disableAnimation接口。

  aboutToAppear(): void {this.pageInfos.disableAnimation(true)}

當設置關閉動畫的時候,轉場會顯得很突兀🙃。根據特定需求謹慎設置吧。

臨時設置關閉轉場-單次關閉

NavPathStack中提供的Push, Pop, Replace等接口中可以設置animated參數,默認為true,表示帶有轉場動畫,如果您需要這次操作中沒有動畫,則設置為false即可。

pageStack: NavPathStack = new NavPathStack()this.pageStack.pushPath({ name: "PageOne" }, false)
this.pageStack.pop(false)

跨包動態路由

我們首先看看之前寫的代碼, 在主導航頁的時候,頂部出現了子頁的import語句:

這種方式我們稱之為靜態路由跳轉,這種方式能完成功能,但是存在缺陷

  • 耦合過多,如果頁面不出現這些import語句,在編譯執行的時候,就不用處理這些連帶的資源。
  • 正是因為上個原因,會導致首頁加載時間過長。

動態路由設計的初衷旨在解決多模塊(HAR/HSP)能夠復用相同的邏輯,實現業務模塊之間的解耦,同時支持路由功能的擴展與整合。

系統路由表

上文提到過,動態路由是要解決多模塊復用,解耦。系統路由表借助了Stage模型配置文件機制,在配置文件中添加路由表信息。這樣的話,我們在配置文件中錄入的就是路由表信息,也就是表示路由信息的字符串配置。之后代碼中打開頁面,僅僅指出路由表中配置的那些信息,系統就會找解析好的配置信息,動態調用配置好的方法。這個時候再引入上文中提到的那些靜態資源也不遲。從而實現了頁面懶加載。

讓配置文件知道路由表的存在

很簡單,在每個模塊的module.json5 添加您的路由表配置即可。 module.json5是Stage開發模型中定義好的配置文件,每一個模塊在創建之初都會新建一個這樣的文件。

{"module": {"name": "entry","type": "entry","description": "$string:module_desc","mainElement": "EntryAbility","deviceTypes": ["phone"],"deliveryWithInstall": true,"installationFree": false,"pages": "$profile:main_pages", //這個是我們設置Pages的配置"routerMap": "$profile:router_map", //這個是我們路由導航的文件"abilities": [...],}
}

創建路由文件

很簡單,看您模塊mian_pages頁面在哪里放著,我們的router_map文件就在哪里放著。因為就是同樣的套路,連引用方式都是一樣的,都是$profile:xxxx找到的。創建一個新文件如下所示:

完善路由配置文件

{"routerMap" : [{"name": "PageOne", "pageSourceFile": "src/main/ets/pages/PageOne.ets","buildFunction": "open","data": {"description": "this is PageOne"}}]
}
  • name: 跳轉頁面名稱
  • pageSourceFile: 跳轉目標頁的包內路徑,相對于src的路徑。
  • buildFunction: 跳轉目標頁的入口函數名稱,必須要用@Builder 裝飾器修飾,且位置位于所指文件頂層。才能找到
  • data: 應用自定義字段,可以通過配置項讀取接口,getConfigRouteMap獲取

在代碼文件中補全配置文件中提到的入口函數

跳轉代碼

最后將原來文件中那些沒必要的import, 設置RoutMap屬性的代碼都刪掉。就完成解耦了。

自定義路由表

鏈接中是自定義路由表的實現方式。

參考文章:

CommonAppDevelopment/common/routermodule/README_AUTO_GENERATE.md · HarmonyOS-Cases/Cases - Gitee.com

文檔中心

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75150.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75150.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75150.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

華為開源自研AI框架昇思MindSpore應用案例:基于MindSpore框架實現PWCNet光流估計

如果你對MindSpore感興趣&#xff0c;可以關注昇思MindSpore社區 1 環境準備 1.進入ModelArts官網 云平臺幫助用戶快速創建和部署模型&#xff0c;管理全周期AI工作流&#xff0c;選擇下面的云平臺以開始使用昇思MindSpore&#xff0c;可以在昇思教程中進入ModelArts官網 創建…

虛幻基礎:UI

文章目錄 控件藍圖可以裝載其他控件藍圖可以安裝其他藍圖接口 填充&#xff1a;相對于父組件填充水平框尺寸—填充—0.5&#xff1a;改變填充的尺寸填充—0.5&#xff1a;改變與父組件的距離 錨點&#xff1a;相對于父組件的控件坐標系原點&#xff0c;屏幕比例改變時&#xff…

監控平臺——SkyWalking部署

一、環境準備 先下載SkyWalking安裝包&#xff0c;需要注意的是SkyWalking 版本在10.X以上使用的nacos-client是2.X&#xff0c;如果安裝的Nacos版本是1.X就會存在兼容性的問題。由于本人使用的SpringBoot項目是2.7.X版本&#xff0c;安裝的Nacos版本只能是1.X版本的&#xff…

熱門索尼S-Log3電影感氛圍旅拍LUTS調色預設 Christian Mate Grab - Sony S-Log3 Cinematic LUTs

熱門索尼S-Log3電影感氛圍旅拍LUTS調色預設 Christian Mate Grab – Sony S-Log3 Cinematic LUTs 我們最好的 Film Look S-Log3 LUT 的集合&#xff0c;適用于索尼無反光鏡相機。無論您是在戶外、室內、風景還是旅行電影中拍攝&#xff0c;這些 LUT 都經過優化&#xff0c;可為…

自動化工作流工具的綜合對比與推薦

最近收到很多朋友私信我說&#xff1a;“刷短視頻的時候&#xff0c;總是刷到自動化工作流的工具&#xff0c;有好多直播間都在宣傳&#xff0c;不知道哪款工具好”。我花了點時間&#xff0c;做了一下測試&#xff0c;大家可以參考一下&#xff0c;以下內容&#xff1a; 以下…

fircrawl本地部署

企業內部的網站作為知識庫給dify使用&#xff0c;使用fircrawl來爬蟲并且轉換為markdown。 ? git clone https://github.com/mendableai/firecrawl.gitcd ./firecrawl/apps/api/ cp .env.example .env cd ~/firecrawl docker compose up -d 官方&#xff1a; https://githu…

day17 學習筆記

文章目錄 前言一、數組的增刪改查1.resize函數2.append函數3.insert函數4.delete函數5.argwhere函數6.unique函數 二、統計函數1.amax&#xff0c;amin函數2.ptp函數3.median函數4.mean函數5.average函數6.var&#xff0c;std函數 前言 通過今天的學習&#xff0c;我掌握了num…

CentOS 8 Stream 配置在線yum源參考 —— 筑夢之路

CentOS 8 Stream ISO 文件下載地址&#xff1a;http://mirrors.aliyun.com/centos-vault/8-stream/isos/x86_64/CentOS-Stream-8-20240603.0-x86_64-dvd1.isoCentOS 8 Stream 網絡引導ISO 文件下載地址&#xff1a;http://mirrors.aliyun.com/centos-vault/8-stream/isos/x86_6…

網絡原理-TCP/IP

網絡原理學習筆記&#xff1a;TCP/IP 核心概念 本文是我在學習網絡原理時整理的筆記&#xff0c;主要涵蓋傳輸層、網絡層和數據鏈路層的核心協議和概念&#xff0c;特別是 TCP, UDP, IP, 和以太網。 一、傳輸層 (Transport Layer) 傳輸層負責提供端到端&#xff08;進程到進…

EF Core 執行原生SQL語句

文章目錄 前言一、執行查詢&#xff08;返回數據&#xff09;1&#xff09; 使用 FromSqlRaw或 FromSqlInterpolated 方法&#xff0c;適用于 DbSet<T>&#xff0c;返回實體集合。2&#xff09;結合 LINQ 查詢3&#xff09;執行任意原生SQL查詢語句&#xff08;使用ADO.N…

Unity LOD Group動態精度切換算法(基于視錐+運動速度)技術詳解

一、動態LOD技術背景與核心挑戰 1. 傳統LOD系統的局限 靜態閾值切換&#xff1a;僅基于距離的切換在動態場景中表現不佳 視覺突變&#xff1a;快速移動時LOD層級跳變明顯 性能浪費&#xff1a;靜態算法無法適應復雜場景變化 對惹&#xff0c;這里有一個游戲開發交流小組&…

MyBatis復雜查詢——一對一、一對多

目錄 &#xff08;一&#xff09;復雜查詢&#xff1a;1對1關系 【任務】數據庫里有學生表(student)和學生證信息表(student_card)&#xff0c;表結構如下所示&#xff0c;要求使用MyBatis框架查詢所有的學生信息以及每位學生的學生證信息 解決方案1&#xff1a;關聯查詢實現…

【服務端】使用conda虛擬環境部署Django項目

寫在開頭 為了與客戶端的Deep search配合&#xff0c;需要整一個后臺管理來保存和管理deep search的數據資料。選擇前端框架Vue-Vben-Admin Django后臺服務來實現這個項目。 廢話結束&#xff0c;從零開始。。。。 一、環境搭建 1. 安裝 Anaconda 下載 Anaconda&#xff1…

Python爬蟲-爬取大麥網演出詳情頁面數據

前言 本文是該專欄的第50篇,后面會持續分享python爬蟲干貨知識,記得關注。 本文,筆者以大麥網平臺為例。基于Python,實現獲取演出詳情頁面的演出信息。 廢話不多說,具體實現思路和詳細邏輯,筆者將在正文結合完整代碼進行詳細介紹。接下來,跟著筆者直接往下看正文詳細內…

多onnx模型導出合并調研(文本檢測+方向分類+文本識別)

??主頁:吾名招財 ??簡介:工科學碩,研究方向機器視覺,愛好較廣泛… ???簽名:面朝大海,春暖花開! 多onnx模型合并導出調研(文本檢測+方向分類+文本識別) 引言1,嘗試合并兩個模型(文本方向分類+文本識別模型)(并行合并)(1)文本方向分類(2)文本識別模型(…

Flink介紹——實時計算核心論文之S4論文詳解

引入 在上一篇我們對Flink的發展歷史有了全局的了解&#xff0c;下面我們會通讀幾篇分布式實時處理相關的重要論文&#xff0c;從S4到Storm&#xff0c;再從MillWheel到Dataflow&#xff0c;最后到Flink。 通過深入梳理分布式實時處理技術的發展脈絡&#xff0c;了解這些年技…

【商城實戰(97)】ELK日志管理系統的全面應用

【商城實戰】專欄重磅來襲!這是一份專為開發者與電商從業者打造的超詳細指南。從項目基礎搭建,運用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用戶、商品、訂單等核心模塊開發,再到性能優化、安全加固、多端適配,乃至運營推廣策略,102 章內容層層遞進。無論是想…

Linux系統-ls命令

一、ls命令的定義 Linux ls命令&#xff08;英文全拼&#xff1a;list directory contents&#xff09;用于顯示指定工作目錄下之內容&#xff08;列出目前工作目錄所含的文件及子目錄)。 二、ls命令的語法 ls [選項] [目錄或文件名] ls [-alrtAFR] [name...] 三、參數[選項…

游戲被外掛攻破?金融數據遭篡改?AI反作弊系統實戰方案(代碼+詳細步驟)

一、背景與需求分析 隨著游戲行業與金融領域的數字化進程加速,作弊行為(如游戲外掛、金融數據篡改)日益復雜化。傳統基于規則的防御手段已難以應對新型攻擊,而AI技術通過動態行為分析、異常檢測等能力,為安全領域提供了革命性解決方案。本文以游戲反作弊系統和金融數據安…

Node.js 路由 - 初識 Express 中的路由

目錄 Node.js 路由 - 初識 Express 中的路由 1. 什么是路由&#xff1f; 2. 安裝 Express 3. 創建 server.js 4. 運行服務器 5. 測試路由 5.1 訪問主頁 5.2 訪問用戶路由 5.3 發送 POST 請求 6. 結語 1. 什么是路由&#xff1f; 路由&#xff08;Routing&#xff09…