HarmonyOS ArkTS 从 Router 到 Navigation 的迁移指南
HarmonyOS 在 ArkTS/ArkUI 架构中逐步把传统的页面路由机制(
@ohos.router)替换为更现代的组件导航机制 Navigation 。本文详细讲解为什么要迁移、迁移的核心步骤、对照示例和最佳实践。 华为开发者
一、背景:为什么要从 Router 迁移到 Navigation
HarmonyOS 在早期版本使用 router 模块来处理页面跳转,这类似于传统的 URL 路由方式:
- 使用
router.pushUrl(...)实现页面跳转 - 使用
router.back()实现返回
但随着 ArkTS 的发展,官方提出:
Navigation 是未来推荐的导航机制 ,它提供了更丰富的动效、更灵活的栈操作、更统一的生命周期管理和更好的组件化路由支持。 华为开发者
Router 的短板
| 项 | Router | Navigation |
|---|---|---|
| 路由控制方式 | 基于 URL | 基于组件栈 |
| 栈管理能力 | 简单 | 强(push/pop/replace 等) |
| 动效 & 页面过渡 | 弱 | 原生支持更丰富效果 |
| 嵌套路由 & 组合场景 | 不支持 | 内建支持 |
| 推荐程度 | ❌ 不推荐 | ✅ 官方推荐 |
简而言之,Router 更像是"旧时代的全局跳转",而 Navigation 是"组件级页面栈导航",更适合现代声明式 UI 架构。 Gitee
二、核心对比:Router vs Navigation
Router 示例(传统跳转)
typescript
import router from '@ohos.router';
@Entry
@Component
struct FirstPage {
toSecond() {
router.pushUrl({ url: 'pages/Second' });
}
build() {
Button('Go to Second').onClick(() => this.toSecond());
}
}
这种方式虽然简单,但:
- 页面必须在
main_pages.json中注册 - 参数只能串联在 URL Query
- 路由控制逻辑与组件 UI 混在一起 Gitee
Navigation 示例(推荐方式)
Navigation 是一个 UI 级组件容器,负责整个页面栈结构。
less
@Entry
@Component
struct AppRoot {
private navStack: NavPathStack = new NavPathStack();
build() {
Navigation(this.navStack) {
Column() {
Button('Go to Second')
.onClick(() => this.navStack.pushPathByName('SecondPage'));
}
}
}
}
这里的路由逻辑与 UI 保持一致,由组件控制栈行为,更声明式。 Gitee
三、迁移步骤详解
1. 准备工作
✅ 确保你的 SDK 版本包含 Navigation 相关 API(通常需要较新版 HarmonyOS SDK)。 ✅ 如果项目使用大量 Router 逻辑,先备份好代码以便回退。 华为开发者
2. 从 Router 跳转改为 navStack.push
Router 调用:
css
router.pushUrl({ url: 'pages/Detail?userId=123' });
迁移后 Navigation 调用:
kotlin
this.navStack.pushPathByName("DetailPage", { userId: 123 });
Navigation 的好处:
- 参数以对象形式传递,不需要手动解析字符串
- NavPathStack 更清晰地控制栈结构 华为开发者
3. 页面结构调整
Router 通常将每个页面标记为 @Entry,导致:
- 多个页面都有独立入口
- 组件结构分散
Navigation 推荐:
只有一个主入口 @Entry,所有页面由 Navigation 管理
scss
@Entry
@Component
struct MainApp {
private navStack = new NavPathStack();
build() {
Navigation(this.navStack) {
NavDestination('HomePage') { HomePage() }
NavDestination('DetailPage') { DetailPage() }
}
}
}
然后你在 UI 中 push 对应名称即可。 Gitee
4. 生命周期 & 动效过渡
Router 点击跳转不会有丰富过渡效果,也无法在组件级监听页面生命周期。
Navigation 支持更丰富的过渡与生命周期钩子(如进入/离开动画、页面 show/hide 钩子)。在迁移时可以根据需求添加过渡效果。 华为开发者
四、做好迁移还要注意这些
Namespace 与模版变化
Navigation 管理页面组件不是用 URL,而是用组件名字或路由表映射名,因此需要统一命名。这比原先的 Router URL 更直观。 Gitee
栈操作更丰富
Navigation 的栈操作不仅仅有 Push 和 Pop,还有:
replacePathByName(...)--- 替换当前页popToName(...)--- 回到指定页面clear()--- 清空栈
这些在 Router 模式中是不支持或者非常难实现的。 Gitee
嵌套路由和组合场景
Navigation 支持嵌套 Navigation 容器,这对于复杂 UI(如底部 Tab + 子导航)非常有用,而 Router 很难实现这种组合效果。 Gitee
五、完整迁移示例对比
Router 版本
php
// FirstPage.ets
router.pushUrl({ url: 'pages/Second' });
// SecondPage.ets
router.back();
Navigation 版本
scss
// AppRoot.ets
Navigation(this.navStack) {
NavDestination('FirstPage') { FirstPage() }
NavDestination('SecondPage') { SecondPage() }
}
// FirstPage.ets
this.navStack.pushPathByName("SecondPage");
// SecondPage.ets
this.navStack.pop();
这样结构更清晰,并且 Navigation 可以嵌套在某一页内部实现"局部导航"效果(如 Tab 内独立导航)。 Gitee
🏁 六、总结
迁移 Router → Navigation 的主要收益:
✔ 更强的组件栈控制能力 ✔ 参数传递更灵活,不再依赖查询字符串 ✔ 更丰富的动画与生命周期支持 ✔ 更易于实现复杂 UI 组合(如嵌套路由、Tab + stack) ✔ 官方推荐,未来生态更加完善 华为开发者