文章配图: 的路由规则、参数传递、返回栈管理、以及回调处理

页面预览

前言

页面跳转是移动应用最基础的能力之一。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 — 无回退栈的页面替换导航。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐