当前位置: 首页 > news >正文

Router 路由管理:pushUrl、replaceUrl、back 与参数传递

前言

在移动应用中,页面路由是连接不同功能模块的纽带。HarmonyOS 提供了@ohos.router模块,支持页面跳转、参数传递、路由栈管理等功能。

“海风日记“全项目共有28 个页面,涉及大量路由跳转场景:从闪屏到首页、从首页到详情、从详情到编辑、从设置页面跳转到子页面等。本文将从源码出发,全面讲解 Router 路由管理的各项 API 和实战用法。


一、Router 模块概述

1.1 引入 Router 模块

在 HarmonyOS 中,所有页面路由操作通过@ohos.router模块实现:

import router from '@ohos.router'

1.2 Router 的核心 API

API功能页面栈影响是否保留当前页
router.pushUrl()跳转到新页面压栈保留
router.replaceUrl()替换当前页面替换栈顶销毁
router.back()返回上一页出栈销毁当前页
router.clear()清空页面栈清空全部销毁
router.getLength()获取栈中页面数无影响-
router.getState()获取当前页面状态无影响-

1.3 路由注册

所有页面必须在main_pages.json中注册:

{ "src": [ "pages/SplashPage", "pages/Index", "pages/onboarding/OnboardingPage", "pages/login/LoginPhonePage", "pages/login/LoginNamePage", "pages/diary/WriteDiaryPage", "pages/diary/EditDiaryPage", "pages/diary/DiaryDetailPage", "pages/diary/DiaryDetail2Page", "pages/calendar/CalendarYearPage", "pages/search/SearchPage", "pages/tag/TagDetailPage", "pages/premium/PremiumPage", "pages/privacy/PrivacyPasswordPage", "pages/image/ImageViewerPage", "pages/mine/ProfileInfoPage", "pages/mine/PersonalSettingsPage", "pages/mine/AccountSettingsPage", "pages/mine/PhoneBindPage", "pages/mine/TagManagePage", "pages/mine/SpaceManagePage", "pages/mine/DataManagePage", "pages/mine/FaqPage", "pages/mine/AboutPage", "pages/mine/EmailFeedbackPage", "pages/mine/DarkModePage" ] }

二、pushUrl:页面跳转

2.1 基本用法

router.pushUrl()将新页面压入栈顶,保留当前页面:

// 跳转到写日记页 Button() { SymbolGlyph($r('sys.symbol.plus')) } .onClick(() => { router.pushUrl({ url: 'pages/diary/WriteDiaryPage' }) })

2.2 带参数跳转

使用params字段传递参数:

// 跳转并传递参数 router.pushUrl({ url: 'pages/diary/DiaryDetailPage', params: { diaryId: item.id } })

2.3 接收参数

目标页面通过router.getParams()接收参数:

@Entry @Component struct DiaryDetailPage { private diary = MOCK_DIARIES[0] aboutToAppear() { const params = router.getParams() as Record<string, string> if (params && params.diaryId) { const found = MOCK_DIARIES.find(d => d.id === params.diaryId) if (found) this.diary = found } } }

2.4 参数传递的方式对比

方式优点缺点适用场景
router.pushUrlparams简单直接参数大小有限制普通参数传递
全局状态共享跨页面共享需要额外状态管理全局用户信息
持久化存储数据持久化读写开销大需要持久化的数据

2.5 pushUrl 的完整参数

interface RouterOptions { url: string // 目标页面路径 params?: Object // 传递的参数 modal?: boolean // 是否以模态方式打开 } // 模态跳转(新页面从底部滑入) router.pushUrl({ url: 'pages/diary/WriteDiaryPage', modal: true })

三、replaceUrl:页面替换

3.1 基本用法

router.replaceUrl()替换当前页面,当前页面会被销毁:

// 登录成功后替换到首页 Button('开始写日记 🌊') .onClick(() => { router.replaceUrl({ url: 'pages/onboarding/OnboardingPage' }) })

3.2 典型应用场景

在“海风日记“中,replaceUrl用于以下场景:

场景源码说明
闪屏 → 登录SplashPage.ets点击登录按钮,替换闪屏
闪屏 → 首页SplashPage.ets点击“直接体验“,跳过登录和引导
登录 → 引导LoginNamePage.ets昵称登录完成后进入引导页
引导 → 首页OnboardingPage.ets引导结束进入首页
退出登录 → 闪屏MineTab.ets退出登录回到闪屏

3.3 pushUrl vs replaceUrl 的选择

// 需要保留返回路径时使用 pushUrl router.pushUrl({ url: 'pages/diary/DiaryDetailPage' }) // 用户可以从详情页返回到首页 // 不需要保留当前页时使用 replaceUrl router.replaceUrl({ url: 'pages/Index' }) // 用户从闪屏进入首页后,无法返回到闪屏

3.4 页面栈的完整流程

“海风日记“应用启动的页面栈变化:

步骤 1:闪屏页 [SplashPage] 步骤 2:点击"登录"(replaceUrl) [LoginPhonePage] 步骤 3:登录成功(replaceUrl) [LoginNamePage] 步骤 4:昵称设置(replaceUrl) [OnboardingPage] 步骤 5:引导结束(replaceUrl) [Index] 步骤 6:点击日记(pushUrl) [Index, DiaryDetailPage] 步骤 7:点击编辑(pushUrl) [Index, DiaryDetailPage, EditDiaryPage] 步骤 8:保存返回(back) [Index, DiaryDetailPage] 步骤 9:返回首页(back) [Index]

四、router.back:返回上一页

4.1 基本用法

// 返回上一页 router.back() // 在导航栏关闭按钮中使用 Button() { SymbolGlyph($r('sys.symbol.xmark')) .fontSize(18).fontColor([COLOR_TEXT_MAIN]) } .backgroundColor('transparent').width(44).height(44) .onClick(() => router.back())

4.2 带参数返回

router.back()支持传递参数给上一页:

// 返回并传递数据 router.back({ url: 'pages/diary/DiaryDetailPage', params: { updated: true } })

4.3 返回指定页面

如果要从深层页面返回到特定页面,可以通过多次back()或使用router.clear()

// 返回到指定页面(需要知道页面路径) router.back({ url: 'pages/Index' })

4.4 返回前的确认

在写日记页面,如果用户有未保存的内容,可以在返回前确认:

Button() { SymbolGlyph($r('sys.symbol.xmark')) } .onClick(() => { if (this.diaryText.length > 0) { // 弹窗确认是否放弃 AlertDialog.show({ title: '放弃编辑?', message: '当前内容尚未保存', primaryButton: { value: '继续编辑', action: () => {} }, secondaryButton: { value: '放弃', action: () => { router.back() } } }) } else { router.back() } })

五、路由参数传递详解

5.1 传递复杂对象

// 传递复杂对象 router.pushUrl({ url: 'pages/diary/DiaryDetailPage', params: { diaryId: '1', source: 'calendar', readOnly: true } })

5.2 接收参数的类型安全

推荐使用类型断言确保参数安全:

interface DiaryDetailParams { diaryId: string source?: string readOnly?: boolean } aboutToAppear() { const params = router.getParams() as DiaryDetailParams if (params?.diaryId) { this.diaryId = params.diaryId } }

5.3 参数验证

在实际项目中,建议对参数进行验证:

aboutToAppear() { const params = router.getParams() as Record<string, string> if (!params) { hilog.error(DOMAIN, TAG, '未收到路由参数') router.back() return } if (!params.diaryId) { hilog.error(DOMAIN, TAG, '缺少 diaryId 参数') router.back() return } // 参数有效,加载数据 this.loadDiary(params.diaryId) }

六、路由模式详解

6.1 标准模式(pushUrl)

// 标准跳转:新页面压入栈顶 router.pushUrl({ url: 'pages/diary/DiaryDetailPage', params: { diaryId: '1' } })

6.2 替换模式(replaceUrl)

// 替换跳转:替换当前页面 router.replaceUrl({ url: 'pages/Index' })

6.3 单例模式

如果希望某个页面在栈中只有一个实例,可以在跳转前检查:

// 检查页面是否已在栈中 const state = router.getState() if (state.name !== 'DiaryDetailPage') { router.pushUrl({ url: 'pages/diary/DiaryDetailPage' }) }

6.4 模式对比

模式API页面栈行为返回行为
标准模式pushUrl新页面压栈可返回
替换模式replaceUrl替换栈顶不可返回
清空模式clear+pushUrl清空栈再压栈不可返回
返回模式back弹出栈顶到上一页

七、页面间的生命周期联动

7.1 路由跳转的生命周期顺序

从页面 A 跳转到页面 B 时,生命周期的执行顺序:

1. 页面 A: aboutToDisappear() 2. 页面 B: aboutToAppear() 3. 页面 B: build() 执行 4. 页面 A: onPageHide() 5. 页面 B: onPageShow()

7.2 返回时的生命周期

从页面 B 返回页面 A 时:

1. 页面 B: aboutToDisappear() 2. 页面 A: aboutToAppear() 3. 页面 A: build() 重新执行 4. 页面 B: onPageHide() 5. 页面 A: onPageShow()

7.3 利用生命周期管理数据

@Entry @Component struct DiaryDetailPage { @State diary: DiaryEntry aboutToAppear() { // 每次进入页面时刷新数据 this.loadDiaryData() } onPageShow() { // 从其他页面返回时刷新 this.loadDiaryData() } loadDiaryData() { const params = router.getParams() as Record<string, string> if (params?.diaryId) { this.diary = MOCK_DIARIES.find(d => d.id === params.diaryId) } } }

八、常见问题与最佳实践

8.1 路由参数未收到

问题:目标页面router.getParams()返回undefined

原因:在build()方法中调用getParams()时,参数可能尚未传递完成。

解决方案:在aboutToAppear()中获取参数:

aboutToAppear() { // 此时参数已可用 const params = router.getParams() as Record<string, string> }

8.2 页面栈溢出

问题:长时间使用后页面跳转异常。

原因:页面栈中积累了大量页面,超过了栈的最大容量(默认 32 个)。

解决方案

// 定期清理页面栈 if (router.getLength() > 20) { // 清空栈后重新跳转 router.clear() router.pushUrl({ url: 'pages/Index' }) }

8.3 跨页面数据同步

问题:页面 A 修改了数据,返回页面 B 后数据未更新。

解决方案:在onPageShow()中刷新数据:

@Entry @Component struct HomeTab { @State diaryList: DiaryEntry[] = MOCK_DIARIES onPageShow() { // 每次页面显示时刷新数据 this.diaryList = [...MOCK_DIARIES] } }

8.4 路由参数的大小限制

router.pushUrlparams参数大小有限制(通常不超过 2KB)。对于大量数据,建议使用全局状态或持久化存储。


总结

本文通过“海风日记“的完整源码,详细讲解了 HarmonyOS Router 路由管理的完整体系:

  1. pushUrl:页面跳转,支持参数传递和模态跳转
  2. replaceUrl:页面替换,适用于登录、引导等场景
  3. router.back:返回上一页,支持参数回传
  4. 参数传递:类型安全、参数验证、复杂对象传递
  5. 路由模式:标准、替换、单例模式的对比和选择
  6. 生命周期联动:路由跳转时的生命周期执行顺序
  7. 最佳实践:页面栈管理、数据同步、参数验证

下一篇文章将深入讲解BarMode.Fixed 与 scrollable 属性,分析 Tab 栏固定模式与滚动模式的选择策略和适配方案,敬请期待。

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


相关资源:

  • @ohos.router API 文档
  • HarmonyOS 页面路由开发指南
  • 页面生命周期文档
  • 海风日记项目源码
  • [HarmonyOS 开发者官网](https://atomgit.com/openharmony/docs
  • 开源鸿蒙跨平台社区
  • ArkUI 导航组件
  • UIAbility 生命周期
http://www.jsqmd.com/news/1216687/

相关文章:

  • 影刀RPA 时间日期处理:定时任务与日期计算完全攻略
  • Java编程语言:从基础到企业级开发全解析
  • 欧米茄中国专柜官方服务电话2026年7月最新,客户热线客户必读 - 欧米茄官方服务中心
  • 佳能TS3380,TS3480,G1810,G2810,G4810,MG3580,MG3680,MG6880,IP2780,IP8780,IX6780故障码5b00,1700,p07,e08,5b02
  • 旅游信息管理系统
  • Codeforces Div.3竞赛解析与算法精讲
  • 深入解析TI OMAP PRCM时钟管理器:从DPLL原理到低功耗实战
  • 2026广州综合防水补漏榜单:看懂卫生间、阳台、地下室与屋顶维修与售后安排 - 盛隆防水
  • Amazon Redshift实战调优:DISTKEY、SORTKEY与WLM配置生死细节
  • Prompt Injection防护实战:基于847测试用例的多层防御框架
  • Display Driver Uninstaller终极指南:3步彻底解决显卡驱动残留问题
  • 鸿蒙 ArkTS 实战:Pinyin Match Fun 从拼音配对乐趣到记录管理完整解析
  • 佳能TR8580,MB5080,IB4080,IX6880,TS6080,TS6180,TS8180,TS9180报错5B00,5B02,5B04,1700,1702,1704,P07,E08清零软件
  • Outlook邮件发送功能原理与实战配置指南
  • 2026年7月最新亨得利官方服务项目及价格查询|服务热线与详细地址权威信息公告 - 亨得利官方博客
  • User-Agent详解:从基础概念到实战应用
  • 浪琴中国官方售后服务中心|全新地址及售后热线权威信息公示(2026年7月最新) - 浪琴服务中心
  • Nintendo Switch大气层系统:如何用3大核心模块打造专业级自定义体验?
  • 北极星指标与领先指标:从用户价值出发的指标设计方法论
  • Java程序设计课程教学体系与实践指南
  • Kimi LeetCode 3621. 位计数深度为 K 的整数数目 I Java实现
  • 2026全国大学生嵌入式竞赛:ESP32-P4/S3边缘AI与物联网开发指南
  • GICD_IROUTER寄存器:嵌入式多核系统中断路由与性能优化实战
  • 给 AI Chat 加上长期记忆:模型提取 + 程序把关 + 规则召回
  • Minecraft RPG服务器新手入门:从客户端配置到躺平变强攻略
  • 2026年7月最新广州番禺区市桥街道亨得利官方名表服务中心电话公示 - 亨得利官方
  • Android应用签名机制详解与安全实践
  • 劳力士中国官方售后服务中心|全部网点地址及电话权威信息通知(2026年7月更新) - 劳力士服务中心
  • OpenClaw技能生态与十大必备Skills安装指南
  • Vue计算属性详解:原理、用法与性能优化