網(wǎng)站開發(fā)工作室 建設(shè) 方案python培訓(xùn)
?(創(chuàng)作不易,感謝有你,你的支持,就是我前行的最大動(dòng)力,如果看完對你有幫助,還請三連支持一波哇ヾ(@^?^@)ノ)
目錄
設(shè)置頁面顯示模式
設(shè)置標(biāo)題欄模式
設(shè)置菜單欄
設(shè)置工具欄
路由操作
頁面跳轉(zhuǎn)
頁面返回
頁面替換
頁面刪除
參數(shù)獲取
路由攔截
子頁面
頁面顯示類型
頁面生命周期
頁面監(jiān)聽和查詢
?組件導(dǎo)航 (Navigation)
Navigation是路由容器組件,一般作為首頁的根容器,包括單欄(Stack)、分欄(Split)和自適應(yīng)(Auto)三種顯示模式。Navigation組件適用于模塊內(nèi)和跨模塊的路由切換,一次開發(fā),多端部署場景。通過組件級路由能力實(shí)現(xiàn)更加自然流暢的轉(zhuǎn)場體驗(yàn),并提供多種標(biāo)題欄樣式來呈現(xiàn)更好的標(biāo)題和內(nèi)容聯(lián)動(dòng)效果。在不同尺寸的設(shè)備上,Navigation組件能夠自適應(yīng)顯示大小,自動(dòng)切換分欄展示效果。
Navigation組件主要包含?導(dǎo)航頁(NavBar)和子頁(NavDestination)。導(dǎo)航頁由標(biāo)題欄(Titlebar,包含菜單欄menu)、內(nèi)容區(qū)(Navigation子組件)和工具欄(Toolbar)組成,其中導(dǎo)航頁可以通過hideNavBar屬性進(jìn)行隱藏,導(dǎo)航頁不存在頁面棧中,導(dǎo)航頁和子頁,以及子頁之間可以通過路由操作進(jìn)行切換。
在API Version 9上,需要配合NavRouter組件實(shí)現(xiàn)頁面路由,從API Version 10開始,推薦使用NavPathStack實(shí)現(xiàn)頁面路由。
設(shè)置頁面顯示模式
Navigation組件通過mode屬性設(shè)置頁面的顯示模式。
自適應(yīng)模式
Navigation組件默認(rèn)為自適應(yīng)模式,此時(shí)mode屬性為NavigationMode.Auto。自適應(yīng)模式下,當(dāng)頁面寬度大于等于一定閾值( API version 9及以前:520vp,API version 10及以后:600vp )時(shí),Navigation組件采用分欄模式,反之采用單欄模式。
Navigation() {...
}
.mode(NavigationMode.Auto)
單頁面模式
圖1?單頁面布局示意圖
將mode屬性設(shè)置為NavigationMode.Stack,Navigation組件即可設(shè)置為單頁面顯示模式。
Navigation() {...
}
.mode(NavigationMode.Stack)
?
分欄模式
圖2?分欄布局示意圖
將mode屬性設(shè)置為NavigationMode.Split,Navigation組件即可設(shè)置為分欄顯示模式。
@Entry
@Component
struct NavigationExample {@State TooTmp: ToolbarItem = {'value': "func", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()private arr: number[] = [1, 2, 3];@BuilderPageMap(name: string) {if (name === "NavDestinationTitle1") {pageOneTmp()} else if (name === "NavDestinationTitle2") {pageTwoTmp()} else if (name === "NavDestinationTitle3") {pageThreeTmp()}}build() {Column() {Navigation(this.pageInfos) {TextInput({ placeholder: 'search...' }).width("90%").height(40).backgroundColor('#FFFFFF')List({ space: 12 }) {ForEach(this.arr, (item:string) => {ListItem() {Text("NavRouter" + item).width("100%").height(72).backgroundColor('#FFFFFF').borderRadius(24).fontSize(16).fontWeight(500).textAlign(TextAlign.Center).onClick(()=>{this.pageInfos.pushPath({ name: "NavDestinationTitle" + item})})}}, (item:string):string => item)}.width("90%").margin({ top: 12 })}.title("主標(biāo)題").mode(NavigationMode.Split).navDestination(this.PageMap).menus([{value: "", icon: "./image/ic_public_search.svg", action: ()=> {}},{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}},{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}},{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}},{value: "", icon: "./image/ic_public_add.svg", action: ()=> {}}]).toolbarConfiguration([this.TooTmp, this.TooTmp, this.TooTmp])}.height('100%').width('100%').backgroundColor('#F1F3F5')}
}// PageOne.ets
@Component
export struct pageOneTmp {@Consume('pageInfos') pageInfos: NavPathStack;build() {NavDestination() {Column() {Text("NavDestinationContent1")}.width('100%').height('100%')}.title("NavDestinationTitle1").onBackPressed(() => {const popDestinationInfo = this.pageInfos.pop() // 彈出路由棧棧頂元素console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))return true})}
}// PageTwo.ets
@Component
export struct pageTwoTmp {@Consume('pageInfos') pageInfos: NavPathStack;build() {NavDestination() {Column() {Text("NavDestinationContent2")}.width('100%').height('100%')}.title("NavDestinationTitle2").onBackPressed(() => {const popDestinationInfo = this.pageInfos.pop() // 彈出路由棧棧頂元素console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))return true})}
}// PageThree.ets
@Component
export struct pageThreeTmp {@Consume('pageInfos') pageInfos: NavPathStack;build() {NavDestination() {Column() {Text("NavDestinationContent3")}.width('100%').height('100%')}.title("NavDestinationTitle3").onBackPressed(() => {const popDestinationInfo = this.pageInfos.pop() // 彈出路由棧棧頂元素console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))return true})}
}
設(shè)置標(biāo)題欄模式
標(biāo)題欄在界面頂部,用于呈現(xiàn)界面名稱和操作入口,Navigation組件通過titleMode屬性設(shè)置標(biāo)題欄模式。
Mini模式
普通型標(biāo)題欄,用于一級頁面不需要突出標(biāo)題的場景。
圖3?Mini模式標(biāo)題欄
Navigation() {...
}
.titleMode(NavigationTitleMode.Mini)
Full模式
強(qiáng)調(diào)型標(biāo)題欄,用于一級頁面需要突出標(biāo)題的場景。
圖4?Full模式標(biāo)題欄
Navigation() {...
}
.titleMode(NavigationTitleMode.Full)
設(shè)置菜單欄
菜單欄位于Navigation組件的右上角,開發(fā)者可以通過menus屬性進(jìn)行設(shè)置。menus支持Array<NavigationMenuItem>和CustomBuilder兩種參數(shù)類型。使用Array<NavigationMenuItem>類型時(shí),豎屏最多支持顯示3個(gè)圖標(biāo),橫屏最多支持顯示5個(gè)圖標(biāo),多余的圖標(biāo)會(huì)被放入自動(dòng)生成的更多圖標(biāo)。
圖5?設(shè)置了3個(gè)圖標(biāo)的菜單欄
let TooTmp: NavigationMenuItem = {'value': "", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}
Navigation() {...
}
.menus([TooTmp,TooTmp,TooTmp])
圖片也可以引用resources中的資源。
let TooTmp: NavigationMenuItem = {'value': "", 'icon': "resources/base/media/ic_public_highlights.svg", 'action': ()=> {}}
Navigation() {...
}
.menus([TooTmp,TooTmp,TooTmp])
圖6?設(shè)置了4個(gè)圖標(biāo)的菜單欄
let TooTmp: NavigationMenuItem = {'value': "", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}
Navigation() {...
}
.menus([TooTmp,TooTmp,TooTmp,TooTmp])
設(shè)置工具欄
工具欄位于Navigation組件的底部,開發(fā)者可以通過toolbarConfiguration屬性進(jìn)行設(shè)置。
圖7?工具欄
let TooTmp: ToolbarItem = {'value': "func", 'icon': "./image/ic_public_highlights.svg", 'action': ()=> {}}
let TooBar: ToolbarItem[] = [TooTmp,TooTmp,TooTmp]
Navigation() {...
}
.toolbarConfiguration(TooBar)
路由操作
Navigation路由相關(guān)的操作都是基于頁面棧NavPathStack提供的方法進(jìn)行,每個(gè)Navigation都需要?jiǎng)?chuàng)建并傳入一個(gè)NavPathStack對象,用于管理頁面。主要涉及頁面跳轉(zhuǎn)、頁面返回、頁面替換、頁面刪除、參數(shù)獲取、路由攔截等功能。
從API version 12開始,頁面棧允許被繼承。開發(fā)者可以在派生類中自定義屬性和方法,也可以重寫父類的方法。派生類對象可以替代基類NavPathStack對象使用。具體示例代碼參見:頁面棧繼承示例代碼。
@Entry
@Component
struct Index {// 創(chuàng)建一個(gè)頁面棧對象并傳入NavigationpageStack: NavPathStack = new NavPathStack()build() {Navigation(this.pageStack) {}.title('Main')}
}
頁面跳轉(zhuǎn)
NavPathStack通過Push相關(guān)的接口去實(shí)現(xiàn)頁面跳轉(zhuǎn)的功能,主要分為以下三類:
普通跳轉(zhuǎn),通過頁面的name去跳轉(zhuǎn),并可以攜帶param。
this.pageStack.pushPath({ name: "PageOne", param: "PageOne Param" }) this.pageStack.pushPathByName("PageOne", "PageOne Param")
帶返回回調(diào)的跳轉(zhuǎn),跳轉(zhuǎn)時(shí)添加onPop回調(diào),能在頁面出棧時(shí)獲取返回信息,并進(jìn)行處理。
this.pageStack.pushPathByName('PageOne', "PageOne Param", (popInfo) => { console.log('Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result)) });
帶錯(cuò)誤碼的跳轉(zhuǎn),跳轉(zhuǎn)結(jié)束會(huì)觸發(fā)異步回調(diào),返回錯(cuò)誤碼信息。
this.pageStack.pushDestinationByName('PageOne', "PageOne Param") .catch((error: BusinessError) => {console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`); }).then(() => { console.error('Push destination succeed.'); });
頁面返回
NavPathStack通過Pop相關(guān)接口去實(shí)現(xiàn)頁面返回功能。
// 返回到上一頁
this.pageStack.pop()
// 返回到上一個(gè)PageOne頁面
this.pageStack.popToName("PageOne")
// 返回到索引為1的頁面
this.pageStack.popToIndex(1)
// 返回到根首頁(清除棧中所有頁面)
this.pageStack.clear()
頁面替換
NavPathStack通過Replace相關(guān)接口去實(shí)現(xiàn)頁面替換功能。
// 將棧頂頁面替換為PageOne
this.pageStack.replacePath({ name: "PageOne", param: "PageOne Param" })
this.pageStack.replacePathByName("PageOne", "PageOne Param")
頁面刪除
NavPathStack通過Remove相關(guān)接口去實(shí)現(xiàn)刪除頁面棧中特定頁面的功能。
// 刪除棧中name為PageOne的所有頁面
this.pageStack.removeByName("PageOne")
// 刪除指定索引的頁面
this.pageStack.removeByIndexes([1,3,5])
參數(shù)獲取
NavPathStack通過Get相關(guān)接口去獲取頁面的一些參數(shù)。
// 獲取棧中所有頁面name集合
this.pageStack.getAllPathName()
// 獲取索引為1的頁面參數(shù)
this.pageStack.getParamByIndex(1)
// 獲取PageOne頁面的參數(shù)
this.pageStack.getParamByName("PageOne")
// 獲取PageOne頁面的索引集合
this.pageStack.getIndexByName("PageOne")
路由攔截
NavPathStack提供了setInterception方法,用于設(shè)置Navigation頁面跳轉(zhuǎn)攔截回調(diào)。該方法需要傳入一個(gè)NavigationInterception對象,該對象包含三個(gè)回調(diào)函數(shù):
名稱 | 描述 |
---|---|
willShow | 頁面跳轉(zhuǎn)前回調(diào),允許操作棧,在當(dāng)前跳轉(zhuǎn)生效。 |
didShow | 頁面跳轉(zhuǎn)后回調(diào),在該回調(diào)中操作棧會(huì)在下一次跳轉(zhuǎn)生效。 |
modeChange | Navigation單雙欄顯示狀態(tài)發(fā)生變更時(shí)觸發(fā)該回調(diào)。 |
說明
無論是哪個(gè)回調(diào),在進(jìn)入回調(diào)時(shí)頁面棧都已經(jīng)發(fā)生了變化。
開發(fā)者可以在willShow回調(diào)中通過修改路由棧來實(shí)現(xiàn)路由攔截重定向的能力。
this.pageStack.setInterception({willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",operation: NavigationOperation, animated: boolean) => {if (typeof to === "string") {console.log("target page is navigation home page.");return;}// 將跳轉(zhuǎn)到PageTwo的路由重定向到PageOnelet target: NavDestinationContext = to as NavDestinationContext;if (target.pathInfo.name === 'PageTwo') {target.pathStack.pop();target.pathStack.pushPathByName('PageOne', null);}}
})
子頁面
NavDestination是Navigation子頁面的根容器,用于承載子頁面的一些特殊屬性以及生命周期等。NavDestination可以設(shè)置獨(dú)立的標(biāo)題欄和菜單欄等屬性,使用方法與Navigation相同。NavDestination也可以通過mode屬性設(shè)置不同的顯示類型,用于滿足不同頁面的訴求。
頁面顯示類型
標(biāo)準(zhǔn)類型
NavDestination組件默認(rèn)為標(biāo)準(zhǔn)類型,此時(shí)mode屬性為NavDestinationMode.STANDARD。標(biāo)準(zhǔn)類型的NavDestination的生命周期跟隨其在NavPathStack頁面棧中的位置變化而改變。
彈窗類型
NavDestination設(shè)置mode為NavDestinationMode.DIALOG彈窗類型,此時(shí)整個(gè)NavDestination默認(rèn)透明顯示。彈窗類型的NavDestination顯示和消失時(shí)不會(huì)影響下層標(biāo)準(zhǔn)類型的NavDestination的顯示和生命周期,兩者可以同時(shí)顯示。
頁面生命周期
Navigation作為路由容器,其生命周期承載在NavDestination組件上,以組件事件的形式開放。
其生命周期大致可分為三類,自定義組件生命周期、通用組件生命周期和自有生命周期(其中aboutToAppear和aboutToDisappear是自定義組件的生命周期。如果NavDestination外層包含自定義組件時(shí)則存在;OnAppear和OnDisappear是組件的通用生命周期,剩下的六個(gè)生命周期為NavDestination獨(dú)有)。
生命周期時(shí)序如下圖所示:
- aboutToAppear:在創(chuàng)建自定義組件后,執(zhí)行其build()函數(shù)之前執(zhí)行(NavDestination創(chuàng)建之前),允許在該方法中改變狀態(tài)變量,更改將在后續(xù)執(zhí)行build()函數(shù)中生效。
- onWillAppear:NavDestination創(chuàng)建后,掛載到組件樹之前執(zhí)行,在該方法中更改狀態(tài)變量會(huì)在當(dāng)前幀顯示生效。
- onAppear:通用生命周期事件,NavDestination組件掛載到組件樹時(shí)執(zhí)行。
- onWillShow:NavDestination組件布局顯示之前執(zhí)行,此時(shí)頁面不可見(應(yīng)用切換到前臺(tái)不會(huì)觸發(fā))。
- onShown:NavDestination組件布局顯示之后執(zhí)行,此時(shí)頁面已完成布局。
- onWillHide:NavDestination組件觸發(fā)隱藏之前執(zhí)行(應(yīng)用切換到后臺(tái)不會(huì)觸發(fā))。
- onHidden:NavDestination組件觸發(fā)隱藏后執(zhí)行(非棧頂頁面push進(jìn)棧,棧頂頁面pop出棧或應(yīng)用切換到后臺(tái))。
- onWillDisappear:NavDestination組件即將銷毀之前執(zhí)行,如果有轉(zhuǎn)場動(dòng)畫,會(huì)在動(dòng)畫前觸發(fā)(棧頂頁面pop出棧)。
- onDisappear:通用生命周期事件,NavDestination組件從組件樹上卸載銷毀時(shí)執(zhí)行。
- aboutToDisappear:自定義組件析構(gòu)銷毀之前執(zhí)行,不允許在該方法中改變狀態(tài)變量。
頁面監(jiān)聽和查詢
為了方便組件跟頁面解耦,在NavDestination子頁面內(nèi)部的自定義組件可以通過全局方法監(jiān)聽或查詢到頁面的一些狀態(tài)信息。
頁面信息查詢
自定義組件提供queryNavDestinationInfo方法,可以在NavDestination內(nèi)部查詢到當(dāng)前所屬頁面的信息,返回值為NavDestinationInfo,若查詢不到則返回undefined。
import { uiObserver } from '@kit.ArkUI';// NavDestination內(nèi)的自定義組件@Componentstruct MyComponent {navDesInfo: uiObserver.NavDestinationInfo | undefinedaboutToAppear(): void {this.navDesInfo = this.queryNavDestinationInfo();}build() {Column() {Text("所屬頁面Name: " + this.navDesInfo?.name)}.width('100%').height('100%')}}
頁面狀態(tài)監(jiān)聽
通過@ohos.arkui.observer提供的注冊接口可以注冊NavDestination生命周期變化的監(jiān)聽,使用方式如下:
uiObserver.on('navDestinationUpdate', (info) => {console.info('NavDestination state update', JSON.stringify(info));});
也可以注冊頁面切換的狀態(tài)回調(diào),能在頁面發(fā)生路由切換的時(shí)候拿到對應(yīng)的頁面信息NavDestinationSwitchInfo,并且提供了UIAbilityContext和UIContext不同范圍的監(jiān)聽:
// 在UIAbility中使用import { UIContext, uiObserver } from '@kit.ArkUI';// callBackFunc 是開發(fā)者定義的監(jiān)聽回調(diào)函數(shù)function callBackFunc(info: uiObserver.NavDestinationSwitchInfo) {}uiObserver.on('navDestinationSwitch', this.context, callBackFunc);// 可以通過窗口的getUIContext()方法獲取對應(yīng)的UIContentuiContext: UIContext | null = null;uiObserver.on('navDestinationSwitch', this.uiContext, callBackFunc);