引入:多頁面應用的路由管理需求
在真實應用開發中,幾乎所有的應用都需要多個頁面來組織功能。比如電商應用需要首頁、商品詳情頁、購物車、個人中心等頁面;社交應用需要聊天列表、聊天窗口、設置等頁面。如何優雅地管理這些頁面之間的跳轉、參數傳遞和返回邏輯,就成為了應用架構的核心問題。HarmonyOS提供了兩種主要的路由方案:Router模塊和Navigation組件,它們共同構成了應用的中樞神經系統。
一、Router模塊基礎使用
核心概念
Router模塊是HarmonyOS最初提供的頁面路由方案,通過URL進行頁面跳轉和管理。雖然在新版本中推薦使用Navigation組件,但瞭解Router仍很重要,特別是在維護現有項目時。
基本頁面跳轉
// 文件:pages/Index.ets
import { router } from '@kit.ArkUI';
@Entry
@Component
struct Index {
build() {
Column() {
Button('跳轉到詳情頁')
.onClick(() => {
// 使用pushUrl保留當前頁面
this.getUIContext().getRouter().pushUrl({
url: 'pages/DetailPage'
}, router.RouterMode.Standard, (err) => {
if (err) {
console.error(`跳轉失敗: ${err.code}, ${err.message}`);
return;
}
console.info('跳轉成功');
})
})
Button('替換當前頁面')
.onClick(() => {
// 使用replaceUrl替換當前頁面
this.getUIContext().getRouter().replaceUrl({
url: 'pages/LoginPage'
})
})
}
}
}
兩種跳轉模式對比
Router模塊提供兩種跳轉模式和兩種實例模式:
|
跳轉模式
|
特點
|
適用場景
|
|
pushUrl
|
保留當前頁,壓入頁面棧
|
需要返回的頁面跳轉
|
|
replaceUrl
|
替換當前頁,銷燬當前頁
|
登錄後跳轉,不需要返回
|
// Single模式示例:確保頁面唯一性
this.getUIContext().getRouter().pushUrl({
url: 'pages/SettingsPage'
}, router.RouterMode.Single)
二、Navigation組件推薦方案
為什麼選擇Navigation
Navigation組件相比Router模塊具有更豐富的動效、更好的多端部署能力和更靈活的棧操作。從API Version 10開始,推薦使用NavPathStack實現頁面路由。
基本架構搭建
// 文件:pages/Index.ets - 主頁面
@Entry
@Component
struct MainPage {
pageStack: NavPathStack = new NavPathStack()
@Builder
pageMap(name: string) {
if (name === 'ProductDetail') {
ProductDetailPage()
} else if (name === 'ShoppingCart') {
ShoppingCartPage()
}
}
build() {
Navigation(this.pageStack) {
Column() {
List() {
ListItem() {
Text('商品列表項')
.onClick(() => {
// 跳轉到商品詳情頁
this.pageStack.pushPath({ name: 'ProductDetail', param: { id: '123' } })
})
}
}
}
}
.title('商品列表')
.mode(NavigationMode.Stack)
.navDestination(this.pageMap)
}
}
子頁面配置
// 文件:pages/ProductDetail.ets
@Component
export struct ProductDetailPage {
pathStack: NavPathStack = new NavPathStack()
@State productInfo: string = ''
build() {
NavDestination() {
Column() {
Text(this.productInfo)
.fontSize(20)
Button('加入購物車')
.onClick(() => {
this.pathStack.pushPath({ name: 'ShoppingCart' })
})
Button('返回')
.onClick(() => {
this.pathStack.pop()
})
}
}
.title('商品詳情')
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
// 獲取傳遞的參數
const params = context.pathInfo.param as Record<string, string>
this.productInfo = `商品ID: ${params.id}`
})
}
}
三、參數傳遞與接收
Router方式的參數傳遞
// 發送參數
this.getUIContext().getRouter().pushUrl({
url: 'pages/DetailPage',
params: {
productId: '12345',
productName: 'HarmonyOS開發指南',
price: 99.9
}
})
// 接收參數(在目標頁面)
@Entry
@Component
struct DetailPage {
@State productId: string = ''
@State productName: string = ''
onPageShow() {
const params = this.getUIContext().getRouter().getParams() as Record<string, any>
this.productId = params.productId as string
this.productName = params.productName as string
}
build() {
// 頁面內容
}
}
Navigation方式的參數傳遞
// 發送參數
this.pageStack.pushPath({
name: 'ProductDetail',
param: {
id: '123',
title: '商品標題',
price: 199.9
}
})
// 接收參數
@Component
struct ProductDetailPage {
@State productData: object = {}
build() {
NavDestination() {
// 頁面內容
}
.onReady((context: NavDestinationContext) => {
this.productData = context.pathInfo.param as object
})
}
}
四、返回邏輯與結果傳遞
基本返回操作
// Router方式返回
this.getUIContext().getRouter().back() // 簡單返回
this.getUIContext().getRouter().back({
url: 'pages/IndexPage'
}) // 返回到指定頁面
// Navigation方式返回
this.pathStack.pop() // 返回上一頁
this.pathStack.popToIndex(0) // 返回到首頁
this.pathStack.clear() // 清空棧返回到根頁面
帶結果返回
// 在詳情頁返回時傳遞結果
this.getUIContext().getRouter().back({
url: 'pages/IndexPage',
params: {
operationResult: 'success',
message: '商品已成功購買'
}
})
// 在主頁面接收返回結果
@Entry
@Component
struct IndexPage {
@State resultMessage: string = ''
onPageShow() {
const params = this.getUIContext().getRouter().getParams() as Record<string, string>
if (params && params.operationResult) {
this.resultMessage = params.message
// 顯示結果提示
}
}
}
五、路由配置與最佳實踐
路由表配置
對於Navigation組件,需要在工程配置中設置路由表:
// 文件:resources/base/profile/route_map.json
{
"routerMap": [
{
"name": "ProductDetail",
"pageSourceFile": "src/main/ets/pages/ProductDetail.ets",
"buildFunction": "ProductDetailBuilder"
},
{
"name": "ShoppingCart",
"pageSourceFile": "src/main/ets/pages/ShoppingCart.ets",
"buildFunction": "ShoppingCartBuilder"
}
]
}
// 在module.json5中配置
{
"module": {
"pages": "$profile:main_pages",
"routerMap": "$profile:route_map"
}
}
生命週期管理
@Entry
@Component
struct ProductDetailPage {
onPageShow() {
console.info('頁面顯示:商品詳情頁')
// 頁面顯示時的初始化操作
}
onPageHide() {
console.info('頁面隱藏:商品詳情頁')
// 頁面隱藏時的清理操作
}
onBackPress() {
console.info('返回按鈕被點擊')
// 返回true表示自定義返回邏輯,false使用默認邏輯
return false
}
build() {
// 頁面內容
}
}
六、高級特性與性能優化
路由攔截器
// 添加路由前置守衞
router.addBeforeHook(() => {
if (!this.isUserLoggedIn()) {
this.showLoginDialog()
return false // 攔截跳轉
}
return true // 允許跳轉
})
動態路由與懶加載
對於大型項目,可以使用動態路由實現模塊解耦和按需加載:
// 動態導入頁面組件
this.pageStack.pushPath({
name: 'LazyPage',
param: { module: 'advanced' }
})
// 配置動態路由表
@Builder
pageMap(name: string) {
if (name === 'LazyPage') {
// 動態導入,實現懶加載
DynamicImport('lazy-module/src/main/ets/pages/LazyPage')
}
}
總結
Router模塊和Navigation組件共同構成了HarmonyOS應用的路由神經系統。Router模塊適合簡單的頁面跳轉場景,而Navigation組件提供了更強大、更靈活的路由管理能力,特別適合複雜的多頁面應用。
行動建議:
- 新項目優先選擇Navigation組件,享受更豐富的功能和更好的性能
- 合理使用參數傳遞機制,保持頁面間數據傳遞的簡潔性
- 注意頁面棧的管理,避免棧深度過大導致內存問題
- 對於需要登錄驗證的頁面,使用路由攔截器統一處理權限校驗
- 大型項目考慮使用動態路由實現模塊化解耦
通過合理運用路由與導航機制,可以構建出結構清晰、用户體驗良好的多頁面HarmonyOS應用。