HarmonyOS应用开发实战:猫猫大作战-页面注册的完整规则、多页面扩展方案、与 `loadContent` 和 `router` 的协作关系


前言
在 HarmonyOS 应用中,每个页面要想被 router 或 Navigation 路由框架找到,必须先在 main_pages.json 中注册。这个文件是 ArkUI 页面路由的"黄页"——系统通过它知道应用有哪些页面、它们的路径在哪里。
本文以「猫猫大作战」的 entry/src/main/resources/base/profile/main_pages.json 为锚点,讲解页面注册的完整规则、多页面扩展方案、与 loadContent 和 router 的协作关系。
提示:本系列不讲 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/Index ❌ pages/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.json 和 router 中的路径都不能包含文件扩展名。
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.json在resources/base/profile/目录下- 路径相对于
ets/,不要写.ets扩展名 - 所有通过
router/Navigation/loadContent访问的页面必须注册 - 支持多页面列表和子目录组织
- 多个 HAP 模块各自有独立的
main_pages.json
下一篇预告:第 79 篇将深入 router.pushUrl — 基础导航跳转的实现与参数传递。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐


所有评论(0)