HarmonyOS应用《玄象》开发实战:Navigation 容器与 @Entry 路由根的搭建

阅读时长:约 18 分钟 | 难度:★★★★☆ | 篇章:第 1 篇 · 项目架构与设计哲学

对应源码:entry/src/main/ets/pages/Index.etsresources/base/profile/main_pages.json

前言

在 HarmonyOS ArkUI 开发中,路由根 是整个应用页面体系的入口。玄象项目通过 Index.ets + Navigation 容器搭建路由根,承载启动页 SplashPage 与后续所有页面的跳转逻辑。本篇将深入剖析玄象项目的路由根搭建方式,从 @Entry 注解、Navigation 容器、路由表注册,到 router.pushUrl / router.replaceUrl 的差异,全面掌握 HarmonyOS 应用页面跳转的核心机制。

提示:路由体系是应用骨架。良好的路由设计能让后续模块开发事半功倍,反之则会埋下诸多维护陷阱。

一、Index.ets 路由根全貌

1.1 完整源码

typescript 复制代码
import { Colors } from '../common/constants/Colors';
import { SplashPage } from './SplashPage';

@Entry
@Component
struct Index {
  build() {
    Navigation() {
      // 启动页作为初始页面
      SplashPage()
    }
    .hideTitleBar(true)
    .width('100%')
    .height('100%')
    .backgroundColor(Colors.BG_DARK)
  }
}

1.2 关键要素解析

玄象项目的 Index.ets 仅 17 行,却承载了应用路由的核心逻辑:

要素 含义 玄象用途
@Entry 标记组件为页面入口 Index 作为应用启动后第一个加载的页面
@Component 标记 struct 为自定义组件 Index 可被 ArkUI 渲染
Navigation() 路由导航容器 提供页面栈管理与转场动画
SplashPage() 子组件引用 启动页作为初始内容
.hideTitleBar(true) 隐藏默认标题栏 启动页不需要标题栏

提示:@Entry@Component 必须同时使用。仅用 @Component 而无 @Entry 的组件是普通子组件,不能独立加载。

二、@Entry 注解深入解析

2.1 @Entry 的作用

@Entry 注解将一个 @Component 标记为页面入口组件。HarmonyOS 应用启动后,会加载 main_pages.json 中注册的第一个 @Entry 页面。

2.2 @Entry 的使用规范

玄象项目 Index.ets@Entry 使用规范:

  1. 唯一性 :每个 @Entry 必须对应 main_pages.json 中注册的一个页面路径。
  2. 必须配合 @Component@Entry 修饰的 struct 必须同时被 @Component 修饰。
  3. build 方法唯一@Entry 组件的 build 方法返回单个根容器(NavigationColumn 等)。

2.3 @Entry 与普通组件的区别

typescript 复制代码
// @Entry 页面(路由可直达)
@Entry
@Component
struct SplashPage {
  build() {
    // ...
  }
}

// 普通子组件(需被其他组件引用)
@Component
export struct GoldButton {
  build() {
    // ...
  }
}

三、Navigation 容器详解

Navigation 是 ArkUI 提供的 路由导航容器,主要功能包括:

  1. 页面栈管理:自动维护页面入栈 / 出栈。
  2. 转场动画:提供默认的 push / pop 转场动画。
  3. 标题栏管理 :可通过 hideTitleBar(true) 隐藏。
  4. 工具栏管理:支持自定义底部工具栏。
typescript 复制代码
@Entry
@Component
struct Index {
  @Provide('navPathStack') navPathStack: NavPathStack = new NavPathStack();

  build() {
    Navigation(this.navPathStack) {
      // 初始内容
      HomePage()
    }
    .hideTitleBar(true)
    .navDestination(this.PageMap)
  }

  @Builder
  PageMap(name: string) {
    if (name === 'detail') {
      DetailPage()
    } else if (name === 'list') {
      ListPage()
    }
  }
}

提示:玄象项目当前使用 Navigation() 的最简形式,仅承载启动页。本系列后续篇章会演示 NavPathStacknavDestination 的进阶用法。

玄象项目同时使用 Navigation 容器与 router API:

  • Navigation:作为页面容器,提供统一的导航上下文。
  • router.pushUrl:在 Navigation 内部 push 子页面。
  • router.replaceUrl:替换当前页面(无返回)。

四、main_pages.json 路由表

4.1 路由表的作用

main_pages.json 是 HarmonyOS 应用的 路由表 ,声明所有可被 router API 加载的页面路径。未在路由表注册的页面无法跳转。

4.2 玄象项目路由表结构

玄象项目路由表位于 entry/src/main/resources/base/profile/main_pages.json,结构如下:

json5 复制代码
{
  "src": [
    "pages/Index",
    "pages/SplashPage",
    "pages/HomePage",
    "pages/mansion/MansionListPage",
    "pages/mansion/MansionDetailPage",
    "pages/mansion/StarTerritoryPage",
    "pages/yijing/YijingHomePage",
    "pages/yijing/HexagramsPage",
    "pages/yijing/GreatWheelPage",
    "pages/yijing/CastDivinationPage",
    "pages/mingli/BaziInputPage",
    "pages/mingli/MingliAnalysisPage",
    "pages/mingli/FortuneTimelinePage",
    "pages/fengshui/FengshuiHomePage",
    "pages/fengshui/LuopanPage",
    "pages/fengshui/GpsFengshuiPage",
    "pages/fengshui/AiPhotoFengshuiPage",
    "pages/fengshui/FengshuiReportPage",
    "pages/astronomy/LunarCalendarPage",
    "pages/astronomy/MoonPhasesPage",
    "pages/astronomy/SolarTermsPage",
    "pages/astronomy/TwelveCiPage",
    "pages/music/MusicTwelveLawsPage",
    "pages/geography/NineProvincesPage",
    "pages/naming/AiNamingPage",
    "pages/naming/NamingResultPage",
    "pages/assistant/AiAssistantPage",
    "pages/profile/ProfilePage",
    "pages/profile/MembershipPage",
    "pages/stems/HeavenlyStemsPage",
    "pages/stems/SixtyJiaziPage"
  ]
}

4.3 路由表注册规范

玄象项目的路由表注册遵循以下规范:

  1. 路径以 pages/ 开头 :与 ets/pages/ 目录结构对应。
  2. 省略 .ets 后缀:路由表声明组件名而非文件名。
  3. Index 必须注册 :作为应用主入口,pages/Index 必须出现在路由表。
  4. @Entry 组件必须注册 :每个 @Entry 修饰的页面都需要注册。

提示:路由表缺失会导致 router.pushUrl 跳转失败。玄象项目在 DevEco Studio 中通过"配置路由"功能自动维护路由表。

五、router.pushUrl 与 router.replaceUrl

5.1 pushUrl:入栈跳转

router.pushUrl 将目标页面压入页面栈,用户可通过返回键回到前一页面。

typescript 复制代码
import { router } from '@kit.ArkUI';

// 跳转到星宿列表页
router.pushUrl({ url: 'pages/mansion/MansionListPage' });

5.2 replaceUrl:替换跳转

router.replaceUrl 用目标页面替换当前页面,无返回栈记录。

typescript 复制代码
import { router } from '@kit.ArkUI';

// 启动页 3 秒后替换为首页
router.replaceUrl({ url: 'pages/HomePage' });

5.3 pushUrl 与 replaceUrl 对比

维度 router.pushUrl router.replaceUrl
栈操作 入栈 替换栈顶
返回键 可返回上一页 无前一页可返回
典型场景 功能页跳转 启动页 → 首页
内存占用 累积增加 等量替换

提示:玄象项目启动页 SplashPagereplaceUrl 跳转到首页,避免用户按返回键回到启动页。

5.4 携带参数的跳转

玄象项目支持携带参数的跳转,通过 params 字段传递:

typescript 复制代码
// 携带星宿 ID 跳转到详情页
router.pushUrl({
  url: 'pages/mansion/MansionDetailPage',
  params: {
    mansionId: 'jiao',
    mansionName: '角宿'
  }
});

// 在目标页面接收参数
@Entry
@Component
struct MansionDetailPage {
  @State mansionId: string = router.getParams()['mansionId'];
  @State mansionName: string = router.getParams()['mansionName'];
}

六、玄象项目路由流转全貌

6.1 启动流转

text 复制代码
应用启动
   ↓
EntryAbility.onWindowStageCreate()
   ↓
windowStage.loadContent('pages/Index')
   ↓
Index.build() → Navigation() { SplashPage() }
   ↓
SplashPage aboutToAppear()
   ↓
setTimeout 3 秒
   ↓
router.replaceUrl({ url: 'pages/HomePage' })
   ↓
HomePage.build() 渲染首页

6.2 功能页跳转流转

text 复制代码
HomePage FeatureGrid 九宫格
   ↓
onClick → router.pushUrl({ url: 'pages/mansion/MansionListPage' })
   ↓
MansionListPage.build() 渲染星宿列表
   ↓
ListItem onClick → router.pushUrl({
  url: 'pages/mansion/MansionDetailPage',
  params: { mansionId: 'jiao' }
})
   ↓
MansionDetailPage.build() 渲染星宿详情

提示:玄象项目所有功能页均通过 router.pushUrl 跳转,返回时通过 router.back() 或系统返回键自动出栈。

七、Navigation 容器的进阶用法

玄象项目未来可引入 NavPathStack 实现更灵活的动态路由:

typescript 复制代码
@Entry
@Component
struct Index {
  private navStack: NavPathStack = new NavPathStack();

  build() {
    Navigation(this.navStack) {
      SplashPage()
    }
    .hideTitleBar(true)
  }
}

// 在任意子组件中
this.navStack.pushPath({ name: 'mansionDetail', param: { id: 'jiao' } });

7.2 自定义转场动画

typescript 复制代码
Navigation(this.navStack) {
  // ...
}
.customNavContentTransition((from: NavContentInfo, to: NavContentInfo, op: NavigationOperation) => {
  // 自定义转场动画
  return {
    timeout: 300,
    transition: (transitionProxy) => {
      // 动画实现
    }
  };
})

7.3 Tab 容器组合

玄象项目底部导航栏未来可使用 Tabs 容器替代 @State currentTab 方案:

typescript 复制代码
Tabs() {
  TabContent() {
    HomePage()
  }.tabBar('首页')

  TabContent() {
    ExplorePage()
  }.tabBar('探索')

  TabContent() {
    ProfilePage()
  }.tabBar('我的')
}

八、路由设计的最佳实践

8.1 路由命名规范

玄象项目的路由命名遵循 功能模块/页面名 模式:

text 复制代码
pages/mansion/MansionListPage
pages/yijing/YijingHomePage
pages/fengshui/LuopanPage
  • 目录前缀:与功能模块对应。
  • 页面名后缀 :统一以 Page 结尾。
  • 驼峰命名MansionListPage 而非 mansion_list_page

8.2 路由跳转的封装

玄象项目在 HomePage 中直接调用 router.pushUrl,规模扩大后建议封装路由工具:

typescript 复制代码
// common/utils/RouterUtil.ets
import { router } from '@kit.ArkUI';

export class RouterUtil {
  static push(url: string, params?: Record<string, object>): void {
    router.pushUrl({ url, params });
  }

  static replace(url: string, params?: Record<string, object>): void {
    router.replaceUrl({ url, params });
  }

  static back(): void {
    router.back();
  }

  static getParams<T>(): T {
    return router.getParams() as T;
  }
}

// 使用
RouterUtil.push('pages/mansion/MansionListPage');

8.3 路由守卫

玄象项目未来可引入路由守卫,实现登录校验、权限校验等:

typescript 复制代码
static push(url: string, params?: Record<string, object>): void {
  if (this.requiresAuth(url) && !this.isLoggedIn()) {
    router.pushUrl({ url: 'pages/profile/LoginPage' });
    return;
  }
  router.pushUrl({ url, params });
}

总结

本篇以玄象项目 Index.ets 为蓝本,深入剖析了 HarmonyOS 应用的路由根搭建:从 @Entry 注解、Navigation 容器、main_pages.json 路由表,到 router.pushUrl / router.replaceUrl 的差异与参数传递。掌握这套路由体系,是后续所有 ArkUI 页面实战的基础。

下一篇:《06 · 多 Ability 还是单 Ability?EntryAbility 与 EntryBackupAbility 的取舍》,将带您进入玄象项目的 Ability 设计决策环节。

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


相关资源:

相关推荐
达子66615 小时前
第13章_HarmonyOs开发图解 视频
华为·音视频·harmonyos
fiona202615 小时前
HarmonyOS应用开发实战:猫猫大作战-如何精准设置缓存数量来平衡内存与滚动流畅度
harmonyos·鸿蒙
程序员黑豆15 小时前
鸿蒙应用开发之父子组件传参:@Prop 装饰器使用教程
前端·后端·harmonyos
FF2501_9402285816 小时前
HarmonyOS应用《玄象》开发实战:宜忌标签云:ForEach + padding + borderRadius 的 chip 实现
harmonyos·鸿蒙
程序员黑豆16 小时前
鸿蒙应用开发之V2状态管理:@Local、@ObservedV2、@Trace 使用教程
前端·后端·harmonyos
LEO1111016 小时前
HarmonyOS应用开发实战:猫猫大作战-onHover 触发时机、HoverType 类型判定、与 onTouch 的差异、TV/PC 场景应用四
harmonyos·鸿蒙
程序员黑豆16 小时前
鸿蒙应用开发之@State 装饰器详解:从基本类型到 @Observed/@ObjectLink/@Track 嵌套监听
前端·harmonyos
慧海灵舟16 小时前
鸿蒙南向开发教程 Day 11:GPIO 按键中断与 LED 状态机
华为·harmonyos
LEO1111017 小时前
HarmonyOS应用开发实战:猫猫大作战-HUD 拆成独立子组件、用 `@Prop` 接收父组件得分/时间为锚点,把 @Prop 声明与传递、单向只
harmonyos·鸿蒙