文章配图:Navigation 的核心架构、NavBar 与 NavDestination 的协作方式、与 router

页面预览

前言

在 HarmonyOS 路由体系中,Navigation 组件是官方推荐的新一代导航方案。与传统的 router 相比,Navigation 提供了更强大的页面栈管理、更灵活的分栏布局、更完善的路由拦截能力。从 API 12 开始,官方逐步推荐使用 Navigation 替代 router,并在后续版本中持续增强其能力。

本文以「猫猫大作战」从 router 迁移到 Navigation 的实战为锚点,讲解 Navigation 的核心架构、NavBar 与 NavDestination 的协作方式、与 router 的对比迁移路径。

提示:本系列不讲 ArkTS 基础语法与环境搭建,假设你已跟完第 1–81 篇。本篇是阶段三第 82 篇。

一、Navigation 核心架构

1.1 三大核心概念

Navigation(导航根容器)
    │
    ├── NavBar(导航栏 / 主页)
    │     ├── 标题栏
    │     ├── 菜单栏
    │     └── 内容区
    │
    └── NavDestination(子页面容器)
          ├── 标题栏
          ├── 内容区
          └── 工具栏
组件 角色 说明
Navigation 根容器 包裹所有导航页面,提供分栏能力
NavBar 导航主页 应用中始终存在的页面(类似 Tab 主页)
NavDestination 目标页面 路由跳转的目标页容器

1.2 基础使用

@Entry
@Component
struct AppNavigation {
  private stack: NavPathStack = new NavPathStack();

  build() {
    Navigation(this.stack) {
      // NavBar 内容 — 主菜单
      Column() {
        Text('🐱 猫猫大作战')
          .fontSize(36)
          .fontWeight(FontWeight.Bold)

        Button('开始游戏')
          .onClick(() => {
            this.stack.pushPath({ name: 'pages/GameBoard' });
          })

        Button('🏆 排行榜')
          .onClick(() => {
            this.stack.pushPath({ name: 'pages/Leaderboard' });
          })
      }
    }
    .title('主菜单')
    .navBarWidth('100%')
  }
}

二、Navigation 与 router 对比

2.1 核心差异

对比维度 router Navigation
组件类型 API 函数 声明式组件
页面容器 系统管理页面栈 NavPathStack 显式管理
分栏模式 不支持 支持 Split 单栏/分栏
路由拦截 不支持 setInterception
生命周期 系统自动管理 组件树自然管理
参数传递 params: Object param: Object
返回结果 forResult(API 23+) 原生支持
TS/JS 语法 函数式 声明式
推荐度 旧方案 官方推荐

2.2 代码对比

// router 方式
import { router } from '@kit.ArkUI';
router.pushUrl({
  url: 'pages/Detail',
  params: { id: 1001 }
});

// Navigation 方式
stack.pushPath({
  name: 'pages/Detail',
  param: { id: 1001 }
});

三、NavPathStack 路由栈

3.1 创建与绑定

@Entry
@Component
struct GameApp {
  // 创建路由栈管理器
  private navStack: NavPathStack = new NavPathStack();

  build() {
    // 绑定到 Navigation 容器
    Navigation(this.navStack) {
      this.NavBar()
    }
  }
}

3.2 核心方法

方法 说明 对应 router
pushPath(info) 压入新页面 router.pushUrl
replacePath(info) 替换当前页面 router.replaceUrl
pop() 弹出当前页面 router.back
popToName(name) 弹出到指定页面 router.back({ url })
popToIndex(index) 弹出到指定索引
clear() 清空路由栈 router.clear
getAllPathName() 获取所有页面名 router.getState

四、NavDestination 目标页

4.1 注册式导航

Navigation 使用 navDestination@Builder 注册页面:

@Entry
@Component
struct GameApp {
  private stack: NavPathStack = new NavPathStack();

  build() {
    Navigation(this.stack) {
      this.NavBar()
    }
    .navDestination(this.navDestBuilder)  // 注册页面构建器
  }

  // 页面构建器 — 根据 name 返回对应页面
  @Builder
  navDestBuilder(name: string, param: Object) {
    if (name === 'pages/GameBoard') {
      GameBoard({ param: param })
    } else if (name === 'pages/Leaderboard') {
      Leaderboard({ param: param })
    }
  }
}

@Component
struct GameBoard {
  @State param: Object = {};

  build() {
    NavDestination() {
      Text('游戏棋盘页面')
    }
    .title('游戏进行中')
  }
}

@Component
struct Leaderboard {
  @State param: Object = {};

  build() {
    NavDestination() {
      Text('排行榜页面')
    }
    .title('高分榜')
  }
}

4.2 NavDestination 结构

NavDestination() {
  // 内容区
  Column() {
    Text('页面内容')
  }
}
.title('标题')                    // 标题栏
.menu(this.MenuBuilder)           // 菜单栏
.toolBar(this.ToolBarBuilder)     // 工具栏
.backButtonIcon($r('sys.media.ohos_ic_back'))  // 自定义返回图标
.hideTitleBar(false)              // 隐藏标题栏

五、参数传递

5.1 传递参数

// 发送方
this.stack.pushPath({
  name: 'pages/Leaderboard',
  param: {
    fromPage: 'main_menu',
    highScore: 88888
  }
});

5.2 接收参数

@Component
struct Leaderboard {
  @State highScore: number = 0;
  @State fromPage: string = '';

  aboutToAppear() {
    // 通过 NavPathStack 获取参数
    // 在当前组件中可以通过 @State param 接收
  }
}

六、获取当前路由信息

// 获取页面栈信息
const pathNames = this.stack.getAllPathName();
// ['pages/Index', 'pages/Leaderboard', 'pages/Detail']

const index = this.stack.getIndexByName('pages/Leaderboard');
// 返回 1

const currentName = this.stack.getCurrentName();
// 'pages/Detail'

const size = this.stack.size();
// 3

七、从 router 迁移到 Navigation

7.1 迁移步骤

步骤 1:将根组件改为 Navigation + NavPathStack
步骤 2:将 router.pushUrl → stack.pushPath
步骤 3:将 router.replaceUrl → stack.replacePath
步骤 4:将 router.back → stack.pop
步骤 5:将 router.getParams → navDestination 的 param 参数
步骤 6:注册 navDestination @Builder

7.2 迁移示例

// 迁移前:router
import { router } from '@kit.ArkUI';
router.pushUrl({ url: 'pages/Detail', params: { id: 1 } });

// 迁移后:Navigation
this.stack.pushPath({ name: 'pages/Detail', param: { id: 1 } });

// router.back({ url: 'pages/Index' })
this.stack.popToName('pages/Index');

八、总结

Navigation 是 HarmonyOS 路由体系的官方推荐方案,提供了声明式的页面管理、灵活的 NavPathStack 路由栈、Split 分栏模式等 router 不具备的能力。

核心要点

  • Navigation 是声明式路由容器,NavPathStack 管理页面栈
  • NavBar 为主页,NavDestination 为目标页
  • 通过 navDestination @Builder 注册"路由表"
  • pushPath/pop/clear 对应 router 的 pushUrl/back/clear
  • 官方推荐从 router 迁移到 Navigation

下一篇预告:第 83 篇将深入 NavPathStack 的完整 API——pushPath、replacePath、popToName、clear 等核心方法详解。

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


相关资源:

Logo

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

更多推荐