一次搞懂HarmonyOS NEXT中的兩種導航方式,打造流暢的應用內跳轉體驗
在鴻蒙應用開發中,流暢的頁面導航和路由是提升用戶體驗的關鍵。HarmonyOS NEXT提供了組件導航(Navigation)?和頁面路由(@ohos.router)?兩種主要方式來實現應用內的頁面跳轉24。
它們各有特點,適用于不同場景,甚至能夠協同工作。本文將帶你全面了解如何在鴻蒙Next應用中設置組件間的導航以及頁面路由。
1 組件導航(Navigation):官方推薦的布局容器
Navigation是路由導航的根視圖容器,一般作為頁面(@Entry)的根容器,提供包括單欄(Stack)、分欄(Split)和自適應(Auto)三種顯示模式15。
1.1 核心特性與顯示模式
Navigation組件適用于模塊內和跨模塊的路由切換,通過組件級路由能力實現自然流暢的轉場體驗1。其三種顯示模式如下:
自適應模式(Auto):默認模式。根據屏幕寬度自動切換——當頁面寬度大于等于一定閾值(API version 10及以后為600vp)時采用分欄模式,否則采用單欄模式15。
單頁面模式(Stack):移動端主流模式,每次只顯示一個頁面3。
分欄模式(Split):大屏設備(如平板)分左右欄顯示,通常左側為導航列表,右側為詳情內容3。
typescript
// 設置Navigation顯示模式示例 Navigation() {// 子組件內容 } .mode(NavigationMode.Auto) // 設置為自適應模式
1.2 標題欄模式
Navigation組件通過titleMode屬性設置標題欄模式15:
Mini模式:普通型標題欄,用于一級頁面不需要突出標題的場景15。
Full模式:強調型標題欄,用于一級頁面需要突出標題的場景15。
typescript
Navigation() {// 子組件內容 } .title('頁面標題') // 設置標題 .titleMode(NavigationTitleMode.Mini) // 設置標題欄模式
1.3 路由管理與NavPathStack
Navigation路由相關的操作基于NavPathStack對象進行管理,包括頁面跳轉、返回、替換、刪除等15。
typescript
// 創建NavPathStack實例并綁定到Navigation @Entry @Component struct Index {pageStack: NavPathStack = new NavPathStack() // 創建頁面棧對象build() {Navigation(this.pageStack) {// 頁面內容}.title('首頁').titleMode(NavigationTitleMode.Full)} }
頁面跳轉主要通過NavPathStack的Push相關接口實現:15
typescript
// 普通跳轉 this.pageStack.pushPathByName('PageName', null)// 帶參數和返回回調的跳轉 this.pageStack.pushPathByName('PageOne', 'PageOne Param', (popInfo) => {console.log('Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result)) })
1.4 NavDestination:子頁面的根容器
NavDestination是Navigation子頁面的根容器,用于承載子頁面的特殊屬性以及生命周期等1。它可以設置獨立的標題欄和菜單欄等屬性,使用方法與Navigation相似1。
NavDestination支持兩種顯示類型:1
標準類型(STANDARD):默認類型,生命周期隨其在NavPathStack頁面棧中的位置變化而改變1。
彈窗類型(DIALOG):設置為彈窗類型時,整個NavDestination默認透明顯示。顯示和消失時不會影響下層標準類型NavDestination的顯示和生命周期1。
2 頁面路由(@ohos.router):精細化控制的路由方案
頁面路由(@ohos.router)模塊通過不同的url地址,可以方便地進行頁面路由,輕松地訪問不同的頁面246。
2.1 基本跳轉操作
Router模塊提供了兩種主要的跳轉模式:24
router.pushUrl:目標頁面不會替換當前頁,而是壓入頁面棧。這樣可以保留當前頁的狀態,并且可以通過返回鍵或者調用router.back方法返回到當前頁24。
router.replaceUrl:目標頁面會替換當前頁,并銷毀當前頁。這樣可以釋放當前頁的資源,并且無法返回到當前頁24。
typescript
import { router } from '@kit.ArkUI';:cite[6]// 跳轉到新頁面并保留當前頁 router.pushUrl({url: 'pages/Profile' })// 替換當前頁面 router.replaceUrl({url: 'pages/Profile' })
2.2 路由實例模式
Router模塊提供了兩種實例模式:24
Standard(多實例模式):默認情況下的跳轉模式,每次跳轉都會創建新的頁面實例24。
Single(單實例模式):如果目標頁面的url已經存在于頁面棧中,則會將離棧頂最近的同url頁面移動到棧頂,復用該頁面實例24。
typescript
// Standard模式跳轉 - 創建新實例 router.pushUrl({ url: 'pages/Profile' }, router.RouterMode.Standard)// Single模式跳轉 - 復用現有實例 router.pushUrl({ url: 'pages/Profile' }, router.RouterMode.Single)
2.3 參數傳遞與接收
在跳轉時,可以通過params屬性向目標頁面傳遞參數:24
typescript
// 發送參數 router.pushUrl({url: 'pages/DetailPage',params: {id: 100,title: '商品詳情'} })// 接收參數 const params = router.getParams() as MyParams if (params) {console.log('params.id', params.id)console.log('params.title', params.title) }
2.4 返回與頁面棧管理
Router模塊提供了靈活的返回和頁面棧管理功能:8
typescript
// 返回上一頁 router.back()// 返回指定頁面 router.back({ url: 'pages/HomePage' })// 清空所有歷史頁面,僅保留當前頁面 router.clear()// 獲取當前頁面棧內的頁面數量 const size = router.getLength() console.log('pages stack size = ' + size)
3 Navigation 與 Router 的關系與協作
在實際開發中,Navigation組件和Router模塊各有其定位和適用場景,它們可以協同工作以構建完整的應用導航體系3。
3.1 區別與適用場景
能力 | Navigation | Router |
---|---|---|
定位 | 布局容器,專注于同級頁面的布局管理與視覺導航 | 路由API,提供編程式導航控制 |
頁面棧管理 | ? 僅同級切換 | ? 跨層級跳轉 & 頁面棧維護 |
參數傳遞 | ? 不支持直接傳參 | ? 通過params傳遞JSON對象 |
適用場景 | Tab導航/側邊欄(同級頁面) | 跨頁面跳轉(如首頁→詳情頁) |
動效與生命周期 | ? 支持更豐富的動效和生命周期 | ?? 相對簡單 |
3.2 協同工作模式
在實際項目中,我們通常會結合使用兩種方案:3
Navigation處理整體導航結構:如底部Tab欄、側邊欄等同級頁面切換。
Router處理特定頁面跳轉:在NavDestination內調用@ohos.router實現跨層級跳轉3。
typescript
// 在Navigation的NavDestination內使用Router進行跳轉 @Component struct MyComponent {build() {NavDestination() {Column() {Button('跳轉到詳情頁').onClick(() => {// 使用Router進行跨層級跳轉router.pushUrl({url: 'pages/DetailPage',params: { id: 123 }})})}}.title('我的頁面')} }
4 最佳實踐與避坑指南
4.1 導航配置方式
路由表配置(推薦)3
在
module.json5
中聲明路由表路徑:3
json
{"routerMap": "$profile:route_map" }
在
resources/base/profile/
目錄下創建route_map.json
:3
json
{"routerMap": [{"name": "MainPage","pageSourceFile": "src/main/ets/pages/MainPage.ets","buildFunction": "MainPageBuilder"}] }
使用路由表時需移除navDestination屬性,否則會產生優先級沖突3。
4.2 常見問題與解決方案
1. 預覽器限制:路由表配置的跳轉在預覽器中可能失敗且無報錯提示,需在本地模擬器測試3。
2. NavRouter子組件約束:NavRouter必須包含且僅能包含兩個子組件,且第二個必須是NavDestination,否則跳轉失效3。
3. 路由傳參陷阱:Navigation不支持直接傳參,需結合@ohos.router的params傳遞對象(對象內禁含方法變量)3。
4. 頁面棧管理:頁面棧支持最大數值是32,超出將導致跳轉失敗,需合理管理頁面棧,避免內存泄漏810。
4.3 性能優化建議
分欄模式(Split)適合平板/車機,單頁模式(Stack)節省移動端內存3。
使用NavPathStack.removeByName()?清理無用頁面棧,避免內存泄漏3。
在Standard模式下,注意頁面棧可能增長過快,需監控棧大小10。
Single模式下需注意頁面狀態重置問題10。
5 總結
Navigation是鴻蒙ArkUI的強交互型導航容器,專注于同級頁面的布局管理與視覺導航(如Tab/分欄),需與Router協同實現完整路由能力3。
對于同級頁面切換(如底部Tab欄、側邊欄),優先使用Navigation組件。
對于跨層級頁面跳轉(如首頁→詳情頁),使用Router模塊。
在復雜項目中,可以混合使用兩種方案:用Navigation處理整體導航結構,用Router處理特定頁面跳轉。
開發時優先采用路由表配置,嚴格遵循NavRouter子組件約束,并在模擬器中驗證跳轉邏輯,可高效構建自適應多端導航體系3。
希望本文能幫助你在鴻蒙應用開發中更加得心應手地實現導航和路由功能!