HarmonyOS 应用开发《掌上英语》第16篇:枚举与常量管理:RouterMap 的设计模式
枚举与常量管理RouterMap 的设计模式一、引言在大型应用中路由路径的管理是一件容易被忽视但影响深远的事情。如果每个页面跳转都直接使用字符串字面量一旦路径需要修改将面临全局搜索替换的噩梦——改漏一个就会导致页面跳转失败。我们英语学习 App 包含 40 个页面横跨 4 个 feature 模块路由管理必须做到集中、类型安全、易于维护。RouterMap枚举 RouterTable注册表 RouterModule封装的三层架构正是为此而设计。本文重点分析第一层——RouterMap枚举的设计模式。二、RouterMap字符串枚举的路由表2.1 完整定义// commons/commonLib/src/main/ets/constants/RouterMap.etsexportenumRouterMap{// 主页MAIN_PAGEMainPage,// 登录LOGIN_PAGELoginPage,// -----------------------------------------------------练习CHAPTER_PRACTICE_PAGEChapterPractice,MATERIAL_DOWNLOAD_PAGEMaterialDownload,FEATURE_COURSE_PAGEFeatureCourses,SEARCH_PAGESearchPage,SEARCH_INPUT_PAGESearchQuestionPage,// -----------------------------------------------------课程ANSWER_QUESTIONS_PAGEAnswerQuestionsPage,ANSWER_QUESTIONS_TWO_PAGEAnswerQuestionsTwoPage,ANSWER_REPORT_PAGETestReportPage,EXAM_RESULT_PAGEExamResultPage,GOOD_COURSE_DETAIL_PAGEGoodCourseDetailPage,MY_WRONG_PAGEMyWrongPage,MY_COLLECTION_PAGEMyCollectionPage,MY_NOTE_PAGEMyNotePage,View_NOTE_PAGEViewNotePage,Mock_PAGEMockTestPage,COURSE_INTRODUCTION_PAGECourseIntroductionPage,Level_TWO_PAGESecondListPage,Level_THREE_PAGEThirdListPage,Level_ONE_PAGETopicHomePage,// -----------------------------------------------------我的MESSAGE_CENTER_PAGEMessageCenterPage,SET_UP_PAGESetUpPage,FEEDBACK_PAGEFeedbackPage,FEEDBACK_RECORD_PAGEFeedbackRecordPage,PRIVACY_STATEMENT_PAGEPrivacyStatementPage,PRIVACY_AGREEMENT_PAGEPrivacyAgreementPage,PRIVACY_USE_PAGEPrivacyUseAlertPage,PERSONAL_CENTER_PAGEEditPersonalCenter,ABOUT_PAGEAboutPage,COURSE_PAGECoursePage,PRACTICE_RECORDS_PAGEPracticeRecordsPage,PRACTICE_DETAILS_PAGEPracticeDetailsPage,DAY_PRACTICE_DETAILS_PAGEOneDayPracticeRecordsPage,COLLECTION_PAGECollectionPage,LEARNING_PLAN_PAGELearningPlanSettingPage,REMINDER_SETTING_PAGEReminderSettingPage,MY_ORDER_PAGEMyOrderPage,Order_Detail_PAGEOrderDetailPage,BROWSING_HISTORY_PAGEBrowsingHistoryPage,DASHBOARD_PAGEDashboardPage,DAILY_CHALLENGE_PAGEDailyChallengePage,WORD_CARD_PAGEWordCardPage,SPEECH_EVAL_PAGESpeechEvalPage,}2.2 关键设计决策为什么用字符串枚举而非数字枚举ArkTS 的枚举默认是数字枚举MAIN_PAGE 0但 RouterMap 选择的是字符串枚举。原因有三可读性RouterMap.MAIN_PAGE的值是MainPage在调试、日志和序列化时一目了然。序列化友好路由路径通常需要在配置文件中使用如route_map.json字符串值天然支持 JSON 序列化。与 NavPathStack 兼容HarmonyOS 的NavPathStack.pushPathByName()需要字符串类型的路由名字符串枚举直接满足要求。// RouterModule.push 的实现publicstaticpush(info:NavRouterInfo,animated?:boolean){RouterModule.stack.pushPathByName(info.url,info.param);// url 为字符串}为什么用注释分组而非嵌套枚举你可能注意到代码中使用注释// --- 练习 ---等来分组。为什么不使用嵌套枚举或命名空间因为 ArkTS 不支持枚举嵌套。注释分组是最务实的替代方案——它虽然没有编译期约束但配合 IDE 的代码折叠功能阅读体验尚可。三、RouterTableBuilder 注册表有了枚举定义的路由名还需要将它们与实际的页面 Builder 关联起来。这就是RouterTable的作用// product/entry/src/main/ets/model/RouterTable.etsimport{RouterMap}fromcommonlib;exportclassRouterTable{staticbuilderMap:Mapstring,WrappedBuilder[object]newMap();publicstaticrouterInit(){// 主页RouterTable.builderMap.set(RouterMap.MAIN_PAGE,wrapBuilder(MainEntryBuilder));RouterTable.builderMap.set(RouterMap.LOGIN_PAGE,wrapBuilder(LoginPageBuilder));// 练习模块来自 homepage featureRouterTable.builderMap.set(RouterMap.CHAPTER_PRACTICE_PAGE,wrapBuilder(ChapterPracticeBuilder));RouterTable.builderMap.set(RouterMap.SEARCH_PAGE,wrapBuilder(SearchPageBuilder));// 课程模块来自 topicpage featureRouterTable.builderMap.set(RouterMap.ANSWER_QUESTIONS_PAGE,wrapBuilder(AnswerQuestionsBuilder));RouterTable.builderMap.set(RouterMap.WORD_CARD_PAGE,wrapBuilder(WordCardPageBuilder));RouterTable.builderMap.set(RouterMap.SPEECH_EVAL_PAGE,wrapBuilder(SpeechEvalPageBuilder));// 我的模块来自 minepage featureRouterTable.builderMap.set(RouterMap.SET_UP_PAGE,wrapBuilder(SetUpPageBuilder));RouterTable.builderMap.set(RouterMap.LEARNING_PLAN_PAGE,wrapBuilder(LearningPlanSettingPageBuilder));RouterTable.builderMap.set(RouterMap.DASHBOARD_PAGE,wrapBuilder(DashboardPageBuilder));// ... 40 路由注册}}设计要点builderMap以RouterMap枚举值为 key以WrappedBuilder为 value所有注册集中在routerInit()中统一调用在应用启动时完成wrapBuilder()将Builder函数包装为可反射调用的形式四、RouterModule统一导航封装有了路由表和枚举还需要一个统一的导航工具类来消费它们// commons/commonLib/src/main/ets/utils/RouterModule.etsclassRouterModule{publicstaticstack:NavPathStacknewNavPathStack();// 页面跳转publicstaticpush(info:NavRouterInfo,animated?:boolean){RouterModule.stack.pushPathByName(info.url,info.param,info.onPop,animated);}// 页面替换publicstaticreplace(info:NavRouterInfo){RouterModule.stack.replacePathByName(info.url,info.param);}// 页面回退publicstaticpopTboolean(result?:T,animated?:boolean){RouterModule.stack.pop(result,animated);}// 页面栈清空publicstaticclear(animated?:boolean){RouterModule.stack.clear(animated);}}业务代码中使用时RouterMap 枚举值 RouterModule 的组合确保了类型安全// MainPage.ets - 页面跳转示例RouterModule.push({url:RouterMap.WORD_CARD_PAGE});// 无参数跳转RouterModule.push({url:RouterMap.LOGIN_PAGE,param:false});// 带参数跳转RouterModule.push({url:RouterMap.ANSWER_QUESTIONS_PAGE,param:1});// 字符串参数RouterModule.push({url:RouterMap.WORD_CARD_PAGE,param:{id:1}});// 对象参数对比直接使用字符串字面量// ❌ 不好的做法硬编码字符串RouterModule.push({url:WordCardPage});// 拼写错误不会报错RouterModule.push({url:word-card-page});// 大小写不一致// ✅ 好的做法使用枚举RouterModule.push({url:RouterMap.WORD_CARD_PAGE});// 拼写错误编译报错五、route_map.json与系统路由的桥接除了代码层面的路由管理HarmonyOS 还要求每个 feature 模块在route_map.json中注册 NavDestination 路由{routerMap:[{name:HomePage,pageSourceFile:src/main/ets/pages/MainPage.ets,buildFunction:HomePageBuilder,data:{description:首页}},{name:FeaturedCourses,pageSourceFile:src/main/ets/pages/FeaturedCourses.ets,buildFunction:FeaturedCoursesBuilder,data:{description:精选课程}}]}这里的name值必须与RouterMap枚举的值一致否则运行时无法匹配。因此 RouterMap 枚举值实际上起着代码层路由名 ↔ 系统层路由配置的桥梁作用。六、字符串枚举 vs 数字枚举 vs 常量对象ArkTS 中定义常量有三种主要方式各有优劣方案示例运行时值序列化IDE 提示反向映射字符串枚举enum E { A a }a✅ 友好✅ 完整❌数字枚举enum E { A }0❌ 无意义✅ 完整✅常量对象const E { A: a }a✅ 友好⚠️ 有限❌对于路由管理字符串枚举是最佳选择因为枚举名即文档——RouterMap.WORD_CARD_PAGE比wordCardPage更具语义重构友好——修改枚举值时所有引用处自动更新不可变——const enum在编译期内联无运行时开销统一管理——所有路由路径在一处定义一目了然七、最佳实践统一枚举命名规范模块_功能_PAGE如LEARNING_PLAN_PAGE、ANSWER_QUESTIONS_PAGE。清晰的命名让开发者看到枚举名就能定位到对应模块。注释分组使用// --- 模块名 ---注释对枚举成员进行分组配合 IDE 代码折叠提升可读性。枚举值尽量简短枚举的值用于路由匹配宜短不宜长。例如WordCardPage而非WordCardManagementPage。与 route_map.json 保持同步新增路由时确保RouterMap枚举、route_map.json、RouterTable.routerInit()三者同步更新。参数类型关联对于带参数的路由建议在跳转处加上注释说明参数类型RouterModule.push({url:RouterMap.ANSWER_QUESTIONS_PAGE,param:1asstring,// ⬅️ param: 章节ID字符串});八、总结RouterMap枚举 RouterTable注册表 RouterModule封装的三层路由架构是我们项目中的核心基础设施RouterMap用字符串枚举集中定义 40 路由路径杜绝硬编码RouterTable将枚举值映射到具体的页面 Builder实现声明式路由注册RouterModule在 NavPathStack 之上提供统一的 push/pop/replace/clear 接口这套模式的核心价值在于一处修改全局生效。当你需要修改某个路由路径时只需更新RouterMap枚举值所有引用处自动适配。对于大型多模块项目而言这种集中管理的设计模式是保证代码质量的关键。

相关新闻

【大白话说Java面试题 第177题】【07_Redis篇】第13题:Redis 的持久化机制有哪些?优缺点说说

【大白话说Java面试题 第177题】【07_Redis篇】第13题:Redis 的持久化机制有哪些?优缺点说说

📌 PDF:大白话说Java面试题 — 07_Redis篇 第13题:Redis 的持久化机制有哪些?优缺点说说 📚 回答: 核心考点: Redis 持久化是保障数据安全的核心机制,大厂面试不会只问"RDB 和…

2026/7/17 0:30:03阅读更多 →
Android随笔-startServicebindService

Android随笔-startServicebindService

一、核心区别对比 特性startService()bindService()启动方式直接启动,无需组件绑定需要与组件(Activity/Fragment)绑定生命周期onCreate() → onStartCommand()onCreate() → onBind()与调用者关系调用者与 Service 无直接关联调用者与 Serv…

2026/7/17 0:30:03阅读更多 →
我即世界:很多你以为的“婚姻之苦”,本质上只是人生之苦:穿衣不是为了遮羞,是老人在为自己的老去找一个道德的借口掩盖自己的老去,好比老虎不会暴漏自己的伤口给竞争对手一样,动物界没有穿衣一说

我即世界:很多你以为的“婚姻之苦”,本质上只是人生之苦:穿衣不是为了遮羞,是老人在为自己的老去找一个道德的借口掩盖自己的老去,好比老虎不会暴漏自己的伤口给竞争对手一样,动物界没有穿衣一说

婚姻背锅的真相:你感受到的不幸,是一场被多方合谋的认知陷阱 前阵子那句“普通人本来就很难获得幸福,只不过大家都将它归于婚姻”戳中了无数人。 但很少有人往下再问一层: 为什么我们会下意识把所有不如意都甩锅给婚姻? “结婚=人生圆满”的执念到底是谁灌输给我们的? 铺…

2026/7/17 0:30:03阅读更多 →
MATLAB版AES-256加密工具包:含ECB模式、PKCS#7填充与全轮函数实现

MATLAB版AES-256加密工具包:含ECB模式、PKCS#7填充与全轮函数实现

本文还有配套的精品资源,点击获取 简介:一套开箱即用的MATLAB AES-256加密解决方案,专为兼容MATLAB 2012b及以上版本设计。完整实现AES-256标准核心运算:字节替换(SubBytes/InvSubBytes)、行移位&#x…

2026/7/17 1:45:09阅读更多 →
基于LM358和IRF540N的过流保护电路设计与实现

基于LM358和IRF540N的过流保护电路设计与实现

1. 过流保护电路的基本原理与设计需求过流保护电路是电子系统中不可或缺的安全机制,它的核心功能是监测负载电流并在超过预设阈值时迅速切断电源连接。这种保护机制对于防止设备损坏、避免火灾风险以及延长电子元件寿命都至关重要。在直流电源系统中,过流…

2026/7/17 1:45:09阅读更多 →
农业AI落地实践:从技术突破到田间应用

农业AI落地实践:从技术突破到田间应用

1. 人工智能走向田野的现状与挑战站在华北平原的麦田边,看着金黄的麦浪翻滚,我不禁思考:那些在实验室里叱咤风云的AI算法,何时才能真正融入这片土地?作为一名在农业科技领域摸爬滚打多年的从业者,我见证了A…

2026/7/17 1:45:09阅读更多 →
CRT-Royale-ReShade:终极CRT复古滤镜完整指南

CRT-Royale-ReShade:终极CRT复古滤镜完整指南

CRT-Royale-ReShade:终极CRT复古滤镜完整指南 【免费下载链接】crt-royale-reshade A port of crt-royale from libretro to ReShade 项目地址: https://gitcode.com/gh_mirrors/cr/crt-royale-reshade 你是否怀念老式CRT显示器那种温暖的视觉质感&#xff1…

2026/7/17 1:45:09阅读更多 →
HPM6750EVKMINI评估板转接板设计与实战技巧

HPM6750EVKMINI评估板转接板设计与实战技巧

1. 先楫半导体HPM6750EVKMINI评估板转接板设计背景HPM6750EVKMINI是先楫半导体推出的一款高性能微控制器评估板,搭载了HPM6750系列MCU。这款芯片采用双核RISC-V架构,主频可达816MHz,内置2MB Flash和1MB SRAM,支持多种外设接口。评…

2026/7/17 1:45:09阅读更多 →
从“系统纯净“到“应用自由“:Windows 11 LTSC用户的微软商店回归之旅

从“系统纯净“到“应用自由“:Windows 11 LTSC用户的微软商店回归之旅

从"系统纯净"到"应用自由":Windows 11 LTSC用户的微软商店回归之旅 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 你…

2026/7/17 1:40:08阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/16 8:28:11阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/16 6:53:04阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/16 12:02:41阅读更多 →
VS Code 高效配置与个性化定制全攻略

VS Code 高效配置与个性化定制全攻略

1. VS Code 高效配置基础作为一款轻量级但功能强大的代码编辑器,VS Code 的默认配置已经能满足基本需求,但通过合理调整设置可以大幅提升编码效率。我使用 VS Code 已经有五年多时间,期间尝试过各种配置方案,总结出这套适合大多数…

2026/7/17 0:00:01阅读更多 →
从竞赛代码到桌面工具:让 SuperADD 与 SubspaceAD 真正跑进自己的图像

从竞赛代码到桌面工具:让 SuperADD 与 SubspaceAD 真正跑进自己的图像

在异常检测领域,很多优秀算法最初都是以研究代码的形式发布的。它们能够在固定测试集上复现实验结果,却不一定能被普通用户直接拿来测试自己的图片。尤其是最近很多算法仅提供在固定测试集的测试环境,而gradio的demo演示也不会提供。 对工程应用和在自己的图片上进行测试来…

2026/7/17 0:00:01阅读更多 →
WinRAR高效配置指南:从基础安装到高级压缩实战

WinRAR高效配置指南:从基础安装到高级压缩实战

前几天帮同事处理一个客户发来的压缩包,解压时系统自带的工具弹出一串乱码,换用 WinRAR 却顺利打开了。这种看似简单的场景,恰恰暴露了不同压缩工具在处理非标准编码、分卷压缩或加密文件时的差异。WinRAR 作为一款老牌工具,真正价…

2026/7/17 0:00:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/16 20:13:14阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/16 8:58:42阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/16 17:10:26阅读更多 →