文章配图:navDestination @Builder 的注册机制、严格模式要求、跨模块页面注册以及代码组织的最佳实践

页面预览

前言

Navigation 路由体系的核心设计之一是注册式跳转——所有可能跳转的目标页都通过 navDestination@Builder 统一注册在 Navigation 组件中。这种模式让路由关系一目了然,也支持严格模式下的编译期检查。

本文以「猫猫大作战」的 Navigation 页面系统为锚点,讲解 navDestination @Builder 的注册机制、严格模式要求、跨模块页面注册以及代码组织的最佳实践。

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

一、navDestination @Builder 注册

1.1 基本注册模式

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

  build() {
    Navigation(this.navStack) {
      this.MainMenu()
    }
    .navDestination(this.pageBuilder)   // ← 注册页面构建器
  }

  // 页面构建器 — 根据 name 返回对应页面
  @Builder
  pageBuilder(name: string, param: Object) {
    if (name === 'pages/Index') {
      IndexPage({ param: param })
    } else if (name === 'pages/Leaderboard') {
      LeaderboardPage({ param: param })
    } else if (name === 'pages/Settings') {
      SettingsPage({ param: param })
    }
  }

  @Builder
  MainMenu() {
    Column() {
      Button('排行榜')
        .onClick(() => {
          this.navStack.pushPath({ name: 'pages/Leaderboard', param: { from: 'menu' } })
        })
    }
  }
}

1.2 工作流程

用户点击"排行榜"按钮
    ↓
navStack.pushPath({ name: 'pages/Leaderboard' })
    ↓
Navigation 收到 pushPath 请求
    ↓
调用 pageBuilder('pages/Leaderboard', param)
    ↓
pageBuilder 匹配 name 返回 LeaderboardPage 组件
    ↓
NavDestination 渲染到屏幕上

二、严格模式要求

2.1 严格模式

从 API 12 开始,Navigation 支持 strictMode(严格模式)。开启后,pushPath 调用的 name 必须在 navDestination 中被显式注册:

Navigation(this.navStack) {
  // NavBar 内容
}
.navDestination(this.pageBuilder)
.enableStrictMode(true)  // 开启严格模式

严格模式下的规则:

行为 非严格模式 严格模式
未注册的 name 运行时崩溃 编译期警告
参数类型校验 推荐显式接口
页面管理 按 name 匹配 按 name + 类型匹配

2.2 严格模式下的 Builder 写法

@Builder
pageBuilder(name: string, param: Object) {
  if (name === 'pages/Index') {
    IndexPage({ param: param as IndexParam })
  } else if (name === 'pages/Leaderboard') {
    LeaderboardPage({ param: param as LeaderboardParam })
  }
  // 如果 name 没有匹配任何条件 → 严格模式下编译报错
}

2.3 定义参数接口

// 为每个页面定义参数类型
interface IndexParam {
  fromLogin?: boolean;
}

interface LeaderboardParam {
  highScore: number;
  playerName?: string;
}

interface SettingsParam {
  tab?: number;
}

三、多模块页面注册

3.1 拆分为多个 Builder

当页面数量增多时,拆分为多个 Builder 文件:

// pageBuilder.ets — 统一路由表
@Builder
export function PageBuilder(name: string, param: Object) {
  if (name.startsWith('pages/game/')) {
    GamePageBuilder(name, param)
  } else if (name.startsWith('pages/user/')) {
    UserPageBuilder(name, param)
  } else if (name.startsWith('pages/shop/')) {
    ShopPageBuilder(name, param)
  }
}

// gamePages.ets
@Builder
function GamePageBuilder(name: string, param: Object) {
  if (name === 'pages/game/Board') {
    GameBoard({ param })
  } else if (name === 'pages/game/Over') {
    GameOver({ param })
  }
}

3.2 跨 HAP 模块注册

// feature 模块暴露的路由注册函数
export function registerRankingRoutes(stack: NavPathStack) {
  stack.pushPath({
    name: 'pages/ranking/Main',
    param: {}
  })
}

// entry 模块使用
import { registerRankingRoutes } from '@ohos/rankingFeature';
registerRankingRoutes(this.navStack);

四、 navDestination 与 NavigationMode

4.1 NavigationMode 导航模式

this.navStack.pushPath({
  name: 'pages/Leaderboard',
  mode: NavigationMode.STANDARD    // 标准模式(默认)
  // mode: NavigationMode.REPLACE  // 替换模式
})
模式 说明
STANDARD 标准压栈(默认)
REPLACE 替换当前栈顶页

五、总结

navDestination @Builder 是 Navigation 的"路由表",通过集中注册页面名称到组件映射关系,实现 type-safe 的页面跳转。

核心要点

  • .navDestination(this.pageBuilder) 注册所有目标页
  • @Builder 中通过 name 匹配返回对应 NavDestination 组件
  • 严格模式(enableStrictMode(true))提供编译期检查
  • 多模块场景下可以拆分多个 Builder
  • NavigationMode 控制压栈/替换模式

下一篇预告:第 86 篇将深入 NavPathStack 的查询 API——getAllPathName、getParamByName 等栈操作。

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


相关资源:

Logo

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