HarmonyOS应用开发实战:猫猫大作战-`router.pushUrl` 的路由规则、参数传递、返回栈管理、以及回调处理
·


前言
页面跳转是移动应用最基础的能力之一。HarmonyOS 提供了 @kit.ArkUI 中的 router 模块来实现页面导航,其中 router.pushUrl 是最核心的跳转 API——它向页面栈中压入一个目标页,用户可以按返回键回到上一页。
本文以「猫猫大作战」中从主菜单跳转到排行榜详情页为场景,讲解 router.pushUrl 的路由规则、参数传递、返回栈管理、以及回调处理。同时为后续第 82 篇 Navigation 新路由体系埋下对比伏笔。
提示:本系列不讲 ArkTS 基础语法与环境搭建,假设你已跟完第 1–78 篇。本篇是阶段三第 79 篇。
一、router.pushUrl 基本用法
1.1 接口签名
import { router } from '@kit.ArkUI';
router.pushUrl(options: RouterOptions): Promise<void>;
router.pushUrl(options: RouterOptions, callback: AsyncCallback<void>): void;
1.2 RouterOptions 参数
interface RouterOptions {
url: string; // 目标页面路径
params?: Object; // 传递的参数
modal?: boolean; // 是否模态(半透明背景)
forResult?: boolean; // 是否需要返回结果(API 23+)
recovery?: string; // 恢复策略(API 21+)
}
| 字段 | 必填 | 说明 |
|---|---|---|
url |
✅ | 目标页面路径,须在 main_pages.json 中注册 |
params |
❌ | 传递给目标页面的参数 |
modal |
❌ | 是否以模态方式打开(背景半透明) |
forResult |
❌ | 是否需要从目标页返回结果 |
recovery |
❌ | 应用恢复时的页面恢复策略 |
1.3 基础跳转示例
import { router } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
build() {
Column() {
Button('🏆 查看排行榜')
.onClick(() => {
// 跳转到排行榜页面
router.pushUrl({
url: 'pages/Leaderboard',
params: {
fromPage: 'main_menu',
highScore: this.highScore
}
}).catch((err: BusinessError) => {
console.error(`跳转失败: ${err.message}`);
});
})
}
}
}
二、页面参数传递
2.1 发送方:通过 params 传参
// Index.ets — 传递参数
router.pushUrl({
url: 'pages/Leaderboard',
params: {
fromPage: 'main_menu',
highScore: this.highScore,
playerName: '猫猫侠',
gameDate: '2026-07-24'
}
});
2.2 接收方:router.getParams 取参
// Leaderboard.ets — 接收参数
@Entry
@Component
struct Leaderboard {
@State fromPage: string = '';
@State highScore: number = 0;
@State playerName: string = '';
@State gameDate: string = '';
aboutToAppear() {
const params = router.getParams() as Record<string, Object>;
this.fromPage = params?.['fromPage'] as string ?? '';
this.highScore = params?.['highScore'] as number ?? 0;
this.playerName = params?.['playerName'] as string ?? '';
this.gameDate = params?.['gameDate'] as string ?? '';
}
build() {
Column() {
Text(`来自: ${this.fromPage}`)
Text(`最高分: ${this.highScore}`)
Text(`玩家: ${this.playerName}`)
Text(`日期: ${this.gameDate}`)
}
}
}
2.3 参数类型建议
| 参数类型 | 是否支持 | 示例 |
|---|---|---|
| string | ✅ | 'hello' |
| number | ✅ | 99999 |
| boolean | ✅ | true |
| Object | ✅ | { name: '猫猫侠', level: 5 } |
| Array | ✅ | [1, 2, 3] |
| Function | ❌ | 不支持序列化 |
| Class 实例 | ⚠️ | 建议序列化为 JSON |
注意:params 中的数据会被序列化传递,Function、Symbol、Date 等非序列化类型会被丢失。
三、页面返回栈管理
3.1 返回栈机制
初始状态:[Index]
pushUrl('Leaderboard') → [Index, Leaderboard]
↑ 当前页
pushUrl('PlayerDetail') → [Index, Leaderboard, PlayerDetail]
↑ 当前页
按返回键 → [Index, Leaderboard]
↑ 当前页(Leaderboard.onPageShow 触发)
按返回键 → [Index]
↑ 当前页(Index.onPageShow 触发)
3.2 router.back 返回
// Leaderboard.ets — 返回到 Index
Button('返回')
.onClick(() => {
router.back(); // 弹出栈顶,回到上一个页面
})
3.3 返回到指定页面
// 返回到指定路径的页面(跳过多层)
router.back({
url: 'pages/Index'
});
3.4 带结果返回(API 23+)
// Index.ets — 跳转时标记 forResult
router.pushUrl({
url: 'pages/Leaderboard',
params: { fromPage: 'main_menu' },
forResult: true
});
// Leaderboard.ets — 返回时带数据
Button('选择并返回')
.onClick(() => {
router.back({
url: 'pages/Index',
params: {
selectedScore: 88888,
selectedPlayer: '猫猫侠'
}
});
})
四、模态跳转
4.1 模态页面
// 以模态方式打开设置页面(半透明背景)
router.pushUrl({
url: 'pages/Settings',
modal: true
});
模态页面的特点:
| 特性 | 普通跳转 | 模态跳转 |
|---|---|---|
| 背景 | 完全替换 | 保留上一页背景(半透明) |
| 返回方式 | 返回键/back() | 返回键/back() |
| 动画 | 页面堆叠 | 底部弹出式动画 |
| 适用场景 | 普通页面跳转 | 设置、弹窗、选项 |
五、错误处理
5.1 常见错误码
router.pushUrl({ url: 'pages/Leaderboard' })
.catch((err: BusinessError) => {
switch (err.code) {
case 100001:
console.error('页面不存在(未在 main_pages.json 中注册)');
break;
case 100002:
console.error('页面栈已满');
break;
case 100003:
console.error('跳转被拦截');
break;
default:
console.error(`未知错误: ${err.code} ${err.message}`);
}
});
| 错误码 | 含义 | 解决方案 |
|---|---|---|
| 100001 | 目标页面不存在 | 检查 main_pages.json 注册 |
| 100002 | 页面栈超限 | 使用 replaceUrl 或清理栈 |
| 100003 | 路由被拦截 | 检查是否设置了路由拦截 |
| 其他 | 系统错误 | 捕获异常并重试 |
5.2 防止重复跳转
// 使用标志位防止按钮连点导致的重复跳转
@State navigating: boolean = false;
goToLeaderboard() {
if (this.navigating) return;
this.navigating = true;
router.pushUrl({ url: 'pages/Leaderboard' })
.then(() => {
this.navigating = false;
})
.catch(() => {
this.navigating = false;
});
}
六、router.pushUrl 与生命周期
6.1 跳转时的生命周期时序
跳转前:Index(当前页面)
↓
router.pushUrl('pages/Leaderboard')
↓
Leaderboard.aboutToAppear() ← 目标页准备
Index.onPageHide() ← 原页隐藏
Leaderboard.build() ← 目标页渲染
Leaderboard.onDidBuild() ← 目标页渲染完成
Leaderboard.onPageShow() ← 目标页可见
↓
用户看到 Leaderboard 页面
6.2 返回时的生命周期时序
返回前:Leaderboard(当前页面)
↓
router.back()
↓
Leaderboard.aboutToDisappear() ← 目标页销毁
Index.onPageShow() ← 原页重新可见
Leaderboard 组件销毁 ← 从页面栈移除
七、router.pushUrl vs Navigation.pushPath
| 对比维度 | router.pushUrl | Navigation.pushPath |
|---|---|---|
| 引入方式 | import { router } from '@kit.ArkUI' |
NavPathStack 实例方法 |
| 页面注册 | main_pages.json | 需 + navDestination @Builder 注册 |
| 参数类型 | params: Object |
param: Object |
| 返回结果 | forResult 参数 |
原生支持结果回调 |
| 拦截能力 | 无 | setInterception 支持 |
| 分栏模式 | 不支持 | 支持 Split 分栏 |
| 官方推荐 | 旧方案 | 推荐方案(新) |
从 API 12 开始,官方推荐使用 Navigation 方案。但理解 router 是理解 Navigation 的基础,且老项目可能仍在大量使用 router。
八、常见踩坑
8.1 坑一:路径前没有加 pages/
// 🚫 错误:路径不完整
router.pushUrl({ url: 'Leaderboard' });
// ✅ 正确:完整路径
router.pushUrl({ url: 'pages/Leaderboard' });
8.2 坑二:页面栈溢出
// 🚫 连续 pushUrl 导致页面栈溢出
for (let i = 0; i < 100; i++) {
router.pushUrl({ url: 'pages/Detail' });
}
// 页面栈默认容量约 32 层,超出会报错 100002
九、总结
router.pushUrl 是 HarmonyOS 经典的路由跳转 API,通过 URL 路径 + params 参数实现页面间导航和通信。虽然官方已推荐使用 Navigation 替代,但理解 router 的页面栈管理、生命周期时序和参数传递机制,仍然是掌握 HarmonyOS 路由体系的基础。
核心要点:
pushUrl向页面栈压入新页面,back()弹出页面params传递页面参数,接收方通过router.getParams()获取- 路径必须与
main_pages.json注册一致,不含.ets扩展 - 模态跳转(
modal: true)支持半透明背景 - 推荐用
forResult实现返回结果传递(API 23+) - 注意防重复跳转和页面栈溢出
下一篇预告:第 80 篇将深入 router.replaceUrl — 无回退栈的页面替换导航。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐


所有评论(0)