Harmony开发之页面路由与导航——应用的中枢神经
引入:多页面应用的路由管理需求
在真实应用开发中,几乎所有的应用都需要多个页面来组织功能。比如电商应用需要首页、商品详情页、购物车、个人中心等页面;社交应用需要聊天列表、聊天窗口、设置等页面。如何优雅地管理这些页面之间的跳转、参数传递和返回逻辑,就成为了应用架构的核心问题。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应用。

浙公网安备 33010602011771号