本篇深入探讨鸿蒙 ArkUI 中的页面路由系统,分析日记应用中三个页面之间的导航关系和参数传递机制。

在这里插入图片描述

一、路由概述

在鸿蒙 ArkUI 中,页面路由通过 @ohos.router 模块实现。日记应用包含三个页面,它们之间形成了清晰的导航关系:

                    ┌──────────────┐
                    │   Index      │
                    │  (日记列表)   │
                    └──────┬───────┘
                           │
              pushUrl ┌────┴────┐ pushUrl
                     ▼          ▼
            ┌────────────┐  ┌──────────────┐
            │  DiaryEdit  │  │ DiaryDetail  │
            │ (编辑/新建) │  │  (详情查看)   │
            └──────┬─────┘  └──────┬───────┘
                   │               │
                   │   pushUrl     │
                   └───────────────┘

二、路由配置

2.1 页面注册

main_pages.json 中注册所有页面:

{
  "src": [
    "pages/Index",
    "pages/DiaryEdit",
    "pages/DiaryDetail"
  ]
}

配置说明:

  • src 数组列出所有页面路径
  • 第一个页面 pages/Index 是应用的入口页面
  • 路径相对于 src/main/ets/ 目录

2.2 页面文件位置

entry/src/main/ets/
├── pages/
│   ├── Index.ets          # 日记列表页
│   ├── DiaryEdit.ets      # 日记编辑页
│   └── DiaryDetail.ets    # 日记详情页

三、路由跳转方式

3.1 pushUrl — 压栈跳转

import router from '@ohos.router'

// 跳转到编辑页(新建模式)
router.pushUrl({
  url: 'pages/DiaryEdit',
  params: { mode: 'create' }
})

// 跳转到详情页
router.pushUrl({
  url: 'pages/DiaryDetail',
  params: { id: diary.id }
})

pushUrl 特点:

  • 将目标页面压入路由栈,当前页面保留在栈底
  • 目标页面可以通过 router.back() 返回当前页面
  • 适合层级导航(列表 → 详情 → 编辑)

3.2 replaceUrl — 替换跳转

router.replaceUrl({
  url: 'pages/Index',
  params: {}
})

replaceUrl 特点:

  • 用目标页面替换当前页面,当前页面出栈
  • 无法通过 router.back() 返回当前页面
  • 适合登录后跳转主页等场景

3.3 back — 返回上一页

// 返回上一页
router.back()

// 返回指定页面
router.back({ url: 'pages/Index' })

3.4 clear — 清空路由栈

router.clear()

清空所有页面,通常在退出应用或切换用户时使用。

四、参数传递

4.1 发送参数

// 发送简单参数
router.pushUrl({
  url: 'pages/DiaryDetail',
  params: { id: 'abc123' }
})

// 发送复杂对象
router.pushUrl({
  url: 'pages/DiaryEdit',
  params: {
    mode: 'edit',
    id: 'abc123',
    title: '日记标题',
    content: '日记内容'
  }
})

4.2 接收参数

aboutToAppear() {
  const params = router.getParams() as Record<string, string>
  if (params) {
    const mode = params.mode    // 'edit' 或 'create'
    const id = params.id        // 日记ID
    const title = params.title  // 日记标题
  }
}

参数接收注意事项:

  • router.getParams() 返回 Object 类型,需要类型断言
  • aboutToAppear 生命周期中获取参数
  • 需要进行空值检查,防止参数缺失导致崩溃

4.3 参数传递的完整示例

Index 页面跳转到 Detail:

// Index.ets
private goToDetail(diaryId: string) {
  router.pushUrl({
    url: 'pages/DiaryDetail',
    params: { id: diaryId }
  })
}

Detail 页面接收参数:

// DiaryDetail.ets
aboutToAppear() {
  const params = router.getParams() as Record<string, string>
  if (params && params.id) {
    this.diaryId = params.id
    this.loadDiaryDetail(params.id)
  }
}

Detail 页面跳转到 Edit:

// DiaryDetail.ets
private goToEdit() {
  router.pushUrl({
    url: 'pages/DiaryEdit',
    params: { mode: 'edit', id: this.diaryId }
  })
}

Edit 页面接收参数:

// DiaryEdit.ets
aboutToAppear() {
  const params = router.getParams() as Record<string, string>
  if (params && params.mode === 'edit') {
    this.isEditMode = true
    this.editId = params.id
    this.loadDiary(params.id)
  }
}

五、路由动画

5.1 默认动画

鸿蒙默认提供页面切换动画:

  • push:从右向左滑入
  • back:从左向右滑出

5.2 自定义动画

router.pushUrl({
  url: 'pages/DiaryDetail',
  params: { id: diaryId },
  animations: {
    duration: 300,
    curve: Curve.EaseInOut,
    direction: AnimationDirection.RightToLeft
  }
})

六、路由模式

6.1 Standard(默认)

router.pushUrl({
  url: 'pages/DiaryDetail',
  params: { id: diaryId }
}, router.RouterMode.Standard)

每次跳转都创建新页面实例,路由栈可能出现多个相同页面。

6.2 Single

router.pushUrl({
  url: 'pages/DiaryDetail',
  params: { id: diaryId }
}, router.RouterMode.Single)

如果路由栈中已有该页面,将其上方的页面全部出栈,复用该页面。

七、路由栈管理

7.1 路由栈结构

初始状态:
┌──────────┐
│  Index   │  ← 栈底
└──────────┘

跳转到 Detail:
┌──────────┐
│ Detail   │  ← 栈顶
├──────────┤
│  Index   │  ← 栈底
└──────────┘

跳转到 Edit:
┌──────────┐
│  Edit    │  ← 栈顶
├──────────┤
│ Detail   │
├──────────┤
│  Index   │  ← 栈底
└──────────┘

back 返回 Detail:
┌──────────┐
│ Detail   │  ← 栈顶
├──────────┤
│  Index   │  ← 栈底
└──────────┘

7.2 获取路由栈信息

const stackSize = router.getLength()
const stack = router.getState()
console.log(`当前路由栈大小: ${stackSize}`)
console.log(`当前页面: ${stack.name}`)

八、路由返回携带参数

8.1 通过全局状态

// 编辑页面保存成功后设置全局状态
AppStorage.Set('diaryUpdated', true)
router.back()

// 列表页面检查
onPageShow() {
  const updated = AppStorage.Get<boolean>('diaryUpdated')
  if (updated) {
    this.loadDiaries()
    AppStorage.Set('diaryUpdated', false)
  }
}

8.2 通过 router.back params

// 编辑页面
router.back({ url: 'pages/Index' })

// 列表页面在 onPageShow 中刷新
onPageShow() {
  this.loadDiaries()
}

九、路由守卫与拦截

虽然鸿蒙没有直接的路由守卫 API,但可以通过封装路由方法实现拦截:

export class RouterUtil {
  static pushUrl(url: string, params?: Record<string, string>) {
    // 前置检查
    if (!this.checkPermission(url)) {
      promptAction.showToast({ message: '无访问权限' })
      return
    }

    router.pushUrl({ url, params })
  }

  static checkPermission(url: string): boolean {
    // 权限检查逻辑
    return true
  }
}

十、总结

鸿蒙路由系统的核心要点:

  1. 页面注册:在 main_pages.json 中声明所有页面
  2. 跳转方式pushUrl(压栈)、replaceUrl(替换)、back(返回)
  3. 参数传递:通过 params 传递,通过 router.getParams() 接收
  4. 路由模式Standard(多实例)和 Single(单例)
  5. 栈管理:理解路由栈结构,合理使用 backclear
  6. 页面刷新:通过 onPageShow 生命周期实现返回后刷新

日记应用的路由设计简洁清晰,列表 → 详情 → 编辑的三层导航是移动应用的经典模式。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐