鸿蒙原生应用实战(一):项目起航 — 从零搭建「纪念日管家」Stage模型应用
·
鸿蒙原生应用实战(一):项目起航 — 从零搭建「纪念日管家」Stage模型应用
本文是「鸿蒙原生应用开发实战」系列第一篇,带你从零搭建一个完整的「纪念日管家」鸿蒙原生应用。这次我们将挑战日期计算、倒计时算法、多页面传参等全新场景。
一、项目背景与功能概览
1.1 为什么做纪念日管家?
在快节奏的现代生活中,我们常常被工作、学习等各种事务占据大部分精力,导致那些对我们个人和家庭有特殊意义的日子容易被遗忘。生日、结婚纪念日、恋爱纪念日、重要节日、体检日、证件到期日……这些看似简单的日期背后,承载着情感、健康、法律等多重价值。
纪念日管家正是为了解决这一痛点而诞生的鸿蒙原生应用。它不仅仅是一个简单的日期记录工具,更是一个智能的生活助手:
核心价值
- 情感连接:帮助用户维系重要的人际关系,不错过每一个值得庆祝的时刻
- 健康管理:定期提醒体检、复查等重要健康事项
- 事务规划:提前规划证件更新、保险续费等生活事务
- 记忆留存:记录生活中的美好瞬间,形成个人专属的时间轴
功能亮点
- 智能首页:今日纪念日醒目提醒 + 未来30天事件预览,让重要日子一目了然
- 灵活添加:支持名称、日期(月/日)、起始年份、7种分类(生日、纪念日、节日、健康、工作、证件、其他)、自定义提前提醒天数
- 高效管理:全部列表支持按分类筛选 + 按日期排序 + 滑动删除,操作流畅便捷
- 沉浸式详情:倒计时大数字视觉展示 + 第N年情感标注 + 实时备注编辑
- 数据洞察:个人中心提供分类统计条形图,直观展示各类纪念日分布
技术优势
作为鸿蒙原生应用,纪念日管家充分利用了HarmonyOS的分布式能力,未来可轻松扩展到手表、平板等多设备协同,实现跨端提醒和数据同步。
1.2 技术栈详解
框架:HarmonyOS Stage 模型
语言:ArkTS (API 23)
SDK:compatibleSdkVersion 6.1.0(23), targetSdkVersion 6.1.1(24)
状态管理:AppStorage(单key: 'events')
导航:@ohos.router(含参数传递)
设备类型:Phone
技术选型解析
-
Stage模型优势:
- 更好的进程管理:按需启动和销毁UIAbility,节省系统资源
- 清晰的生命周期:便于状态管理和内存优化
- 支持多实例:同一应用可打开多个窗口,适合纪念日对比查看
-
ArkTS语言特性:
- 静态类型检查:提高代码健壮性,减少运行时错误
- 声明式UI:简洁高效的界面开发方式
- 生态完善:丰富的API和组件库支持
-
状态管理策略:
- 使用AppStorage全局状态管理,确保数据一致性
- 单key设计简化了数据流,便于调试和维护
- 支持本地持久化,数据安全可靠
-
导航系统:
- @ohos.router提供标准化的页面跳转能力
- 支持参数传递,实现页面间数据共享
- 路由栈管理清晰,用户体验流畅
扩展性考虑
当前版本专注于手机端体验,技术栈设计已为未来扩展预留了接口:
- 可轻松适配平板的大屏布局
- 支持手表端的轻量化提醒功能
- 云端同步能力可基于HarmonyOS分布式数据管理实现
二、项目目录结构
MyApplication/
├── AppScope/
│ ├── app.json5
│ └── resources/
├── entry/
│ └── src/main/
│ ├── ets/
│ │ ├── entryability/
│ │ │ └── EntryAbility.ets # 应用入口
│ │ ├── models/
│ │ │ └── EventData.ets # 数据模型+分类+倒计时算法
│ │ └── pages/
│ │ ├── Index.ets # 首页(今日+即将到来)
│ │ ├── AddEvent.ets # 添加纪念日
│ │ ├── ListPage.ets # 全部列表+分类筛选
│ │ ├── DetailPage.ets # 详情页+倒计时+备注编辑
│ │ └── ProfilePage.ets # 个人中心+分类统计
│ ├── module.json5
│ └── resources/base/profile/main_pages.json
├── build-profile.json5
└── hvigor/
三、Stage 模型与路由(含参数传递)
3.1 页面路由注册
{
"src": [
"pages/Index",
"pages/AddEvent",
"pages/ListPage",
"pages/DetailPage",
"pages/ProfilePage"
]
}
3.2 带参数的路由跳转
纪念日管家的一个独特之处在于 DetailPage 需要接收事件 ID:
// 列表页 → 详情页(携带参数)
router.pushUrl({
url: 'pages/DetailPage',
params: { eventId: ev.id }
});
// 详情页接收参数
aboutToAppear(): void {
let p = router.getParams() as Record<string, Object>;
let eventId = p['eventId'] as string;
// 根据 eventId 查找事件数据...
}
参数传递的注意事项:
- 参数通过
params对象传递 - 接收方用
router.getParams()获取 - 返回值类型为
Record<string, Object>,需要转型 - 使用
as string确保类型安全
3.3 页面路由关系
Index(首页:今日+即将到来)
├─→ AddEvent(添加纪念日)
├─→ ListPage(全部列表+分类筛选)
│ └─→ DetailPage(详情页,带 eventId 参数)
└─→ ProfilePage(个人中心)
四、构建配置
// build-profile.json5
{
app: {
products: [{
targetSdkVersion: "6.1.1(24)",
compatibleSdkVersion: "6.1.0(23)",
runtimeOS: "HarmonyOS",
strictMode: { caseSensitiveCheck: true }
}]
}
}
五、踩坑记录
🕳️ 坑1:router.getParams() 的类型转换
问题:router.getParams() 返回 Record<string, Object>,直接访问 p['eventId'] 类型为 Object,不能直接当字符串使用。
解决:
let p = router.getParams() as Record<string, Object>;
let eventId = p['eventId'] as string; // 显式转型
🕳️ 坑2:MM-DD 格式的日期比较
问题:纪念日只存 MM-DD(不含年份),但需要跨年比较(去年的节日在今天之前还是之后)。
解决:在 getCountdown 函数中分别计算今年和明年的日期:
let targetThisYear = new Date(thisYear, month - 1, day);
let diff = Math.ceil((targetThisYear.getTime() - now.getTime()) / 86400000);
if (diff >= 0) {
// 今年还没过,用今年日期
} else {
// 今年已过,算到明年
let targetNext = new Date(thisYear + 1, month - 1, day);
let nextDiff = Math.ceil(...);
}
六、下篇预告
本篇完成了「纪念日管家」的框架搭建和路由配置。下一篇将深入数据层设计,包括:
- AnniversaryEvent 模型设计(MM-DD 日期格式的哲学)
- 7种事件分类系统的设计
- 倒计时算法(跨年计算 + 第N年标注)
- 提前提醒天数机制
敬请期待!
如果你正在学习鸿蒙开发,欢迎关注本系列!
更多推荐

所有评论(0)