文章配图:页面注册的完整规则、多页面扩展方案、与  和  的协作关系

页面预览

前言

在 HarmonyOS 应用中,每个页面要想被 routerNavigation 路由框架找到,必须先在 main_pages.json 中注册。这个文件是 ArkUI 页面路由的"黄页"——系统通过它知道应用有哪些页面、它们的路径在哪里。

本文以「猫猫大作战」的 entry/src/main/resources/base/profile/main_pages.json 为锚点,讲解页面注册的完整规则、多页面扩展方案、与 loadContentrouter 的协作关系。

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

一、项目中的 main_pages.json

1.1 当前配置

{
  "src": [
    "pages/Index"
  ]
}

当前「猫猫大作战」只有单个页面 Index.ets,所有游戏逻辑(主菜单、游戏棋盘、暂停、游戏结束)都在一个页面内通过 if/else 状态切换。

1.2 路径映射

main_pages.json 中声明的路径
    ↓
"pages/Index"
    ↓
实际文件:entry/src/main/ets/pages/Index.ets
    ↓
loadContent('pages/Index') 或 router.pushUrl({ url: 'pages/Index' })

二、页面注册规则

2.1 语法规则

{
  "src": [
    "pages/Index",
    "pages/Detail",
    "pages/Settings/SettingsPage"
  ]
}
规则 说明 示例
路径相对 ets/ 相对于 entry/src/main/ets/ pages/Index
不含文件扩展名 不要写 .ets pages/Indexpages/Index.ets
支持子目录 可在 pages 下建子目录 pages/Settings/SettingsPage
支持多个页面 注册所有需路由跳转的页面 ["pages/A", "pages/B", ...]

2.2 模块引用规则

module.json5 中引用 main_pages.json

{
  "module": {
    "pages": "$profile:main_pages"
  }
}

$profile:main_pages 指向 resources/base/profile/main_pages.json

三、多页面扩展方案

3.1 为猫猫大作战增加页面

{
  "src": [
    "pages/Index",
    "pages/Leaderboard",
    "pages/Settings",
    "pages/GameHistory",
    "pages/About"
  ]
}

对应的文件目录:

entry/src/main/ets/pages/
├── Index.ets           ← 主游戏页面
├── Leaderboard.ets     ← 排行榜页面
├── Settings.ets        ← 设置页面
├── GameHistory.ets     ← 游戏历史页面
└── About.ets           ← 关于页面

3.2 子目录组织

对于大型应用,使用子目录组织页面:

{
  "src": [
    "pages/Index",
    "pages/game/GameBoard",
    "pages/game/GameOver",
    "pages/user/Login",
    "pages/user/Profile",
    "pages/shop/ShopMain",
    "pages/shop/ItemDetail"
  ]
}

目录结构:

pages/
├── Index.ets
├── game/
│   ├── GameBoard.ets
│   └── GameOver.ets
├── user/
│   ├── Login.ets
│   └── Profile.ets
└── shop/
    ├── ShopMain.ets
    └── ItemDetail.ets

四、通过 router 跳转

4.1 pushUrl 基本用法

// 从 Index 页面跳转到 Leaderboard 页面
import { router } from '@kit.ArkUI';

router.pushUrl({
  url: 'pages/Leaderboard',
  params: {
    pageTitle: '高分排行榜',
    defaultTab: 0
  }
});

4.2 路由路径与 main_pages 的对应

main_pages.json  →  "pages/Leaderboard"
router.pushUrl   →  { url: 'pages/Leaderboard' }
loadContent      →  loadContent('pages/Leaderboard')

三者路径必须完全一致,且都已在 main_pages.json 中注册。

4.3 完整跳转示例

// Index.ets — 排行榜按钮
Button('🏆 排行榜')
  .onClick(() => {
    router.pushUrl({
      url: 'pages/Leaderboard',
      params: {
        fromGame: true,
        highScore: this.highScore
      }
    });
  })

// Leaderboard.ets — 接收参数
@Entry
@Component
struct Leaderboard {
  @State fromGame: boolean = false;
  @State highScore: number = 0;

  aboutToAppear() {
    const params = router.getParams() as Record<string, Object>;
    this.fromGame = params?.['fromGame'] as boolean ?? false;
    this.highScore = params?.['highScore'] as number ?? 0;
  }
}

五、与 Navigation 的配合

如果使用 Navigation 而非 router,main_pages.json 依然需要注册所有页面:

// Navigation 同样依赖 main_pages.json 的注册
@Entry
@Component
struct NavigationPage {
  private stack: NavPathStack = new NavPathStack();

  build() {
    Navigation(this.stack) {
      // NavBar 内容
    }
  }

  // 跳转到 Leaderboard — 路径同样来自 main_pages.json
  goToLeaderboard() {
    this.stack.pushPath({
      name: 'pages/Leaderboard',
      param: { fromGame: true }
    });
  }
}

六、跨模块页面路由

6.1 feature 模块的页面

当应用有多个 HAP/HSP 模块时,feature 模块也有自己的 main_pages.json

// ranking_feature/src/main/resources/base/profile/main_pages.json
{
  "src": [
    "pages/RankingMain",
    "pages/PlayerDetail"
  ]
}

6.2 跨模块跳转

// 从 entry 模块跳转到 ranking_feature 模块的页面
import { common } from '@kit.AbilityKit';
import { Want } from '@kit.AbilityKit';

const want: Want = {
  bundleName: 'com.maomaodazuozhan.game',
  abilityName: 'RankingAbility',
  parameters: { pageType: 'main' }
};
startAbility(want);

七、常见踩坑

7.1 坑一:路径未注册就跳转

// 🚫 错误:url 在 main_pages.json 中不存在
router.pushUrl({ url: 'pages/NotFound' });
// → 崩溃:Cannot find page 'pages/NotFound'

解决方法:在 main_pages.json 中添加对应路径:

{ "src": ["pages/Index", "pages/NotFound"] }

7.2 坑二:路径包含 .ets 扩展名

// 🚫 错误
router.pushUrl({ url: 'pages/Index.ets' });  // ❌ 多写了 .ets

main_pages.jsonrouter 中的路径都不能包含文件扩展名

7.3 坑三:路径大小写不一致

// main_pages.json
{ "src": ["pages/Leaderboard"] }

// router 中写成小写
router.pushUrl({ url: 'pages/leaderboard' });  // ❌ 大小写不匹配

ArkTS 文件名区分大小写,路径必须精确匹配。

八、主从页面注册设计

8.1 单页应用 vs 多页应用

模式 页面数 适用场景 优点 缺点
单页(猫猫大作战当前) 1 游戏、工具类 状态集中管理 代码规模大难维护
多页 2-10 大多数应用 模块化、清晰 页面间需传参
复杂多页 10+ 电商、社交 彻底解耦 路由管理成本高

8.2 推荐:逐步拆分

随着功能增加,可以逐步从单页拆分为多页:

阶段 1(当前):pages/Index(含全部逻辑)
阶段 2:pages/Index + pages/Settings(设置页面)  
阶段 3:pages/Index + pages/Settings + pages/Leaderboard

九、总结

main_pages.json 虽小(当前仅 5 行),但它是页面路由体系的基石——所有页面跳转都依赖它的注册。

核心要点

  • main_pages.jsonresources/base/profile/ 目录下
  • 路径相对于 ets/,不要写 .ets 扩展名
  • 所有通过 router/Navigation/loadContent 访问的页面必须注册
  • 支持多页面列表和子目录组织
  • 多个 HAP 模块各自有独立的 main_pages.json

下一篇预告:第 79 篇将深入 router.pushUrl — 基础导航跳转的实现与参数传递。

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


相关资源:

Logo

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

更多推荐