引入:多頁面應用的路由管理需求

在真實應用開發中,幾乎所有的應用都需要多個頁面來組織功能。比如電商應用需要首頁、商品詳情頁、購物車、個人中心等頁面;社交應用需要聊天列表、聊天窗口、設置等頁面。如何優雅地管理這些頁面之間的跳轉、參數傳遞和返回邏輯,就成為了應用架構的核心問題。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應用。