鸿蒙原生应用实战(五):功能打磨 — 个人中心
·
鸿蒙原生应用实战(五):功能打磨 — 个人中心
本文是系列终篇,完成「纪念日管家」最后一个人中心页面(ProfilePage),并进行三个鸿蒙原生项目(心情日记、习惯打卡、纪念日管家)的全景式技术对比。你将看到同一个技术底座如何适配三种完全不同的业务场景。
一、个人中心页面(ProfilePage.ets)全面拆解
1.1 页面布局
┌──────────────────────────────────────────┐
│ < 返回 我的 │
├──────────────────────────────────────────┤
│ ┌──────────────────────────────────┐ │
│ │ 📅 │ │
│ │ 纪念日管家 │ │ ← 应用信息
│ │ 记住每一个重要的日子 │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 📌 │ │ 🏷️ │ │
│ │ 8 │ │ 7 │ │ ← 统计卡片
│ │ 纪念日 │ │ 分类 │ │
│ └──────────┘ └──────────┘ │
│ │
│ 分类统计 │
│ 🎂 生日 ████████████████ 3个 │ ← 分类分布条形图
│ 🎉 节日 ██████████ 2个 │
│ 💍 纪念日 █████ 1个 │
│ ... │
│ │
│ 🔄 重置数据 清除所有纪念日 > │ ← 功能菜单
│ ℹ️ 关于应用 纪念日管家v1.0.0 > │
└──────────────────────────────────────────┘
1.2 状态变量
@State events: AnniversaryEvent[] = [];
@State total: number = 0;
@State categories: EventCategory[] = [];
1.3 分类统计条形图
ForEach(this.categories, (c: EventCategory) => {
// 只显示有事件数量的分类
if (this.getCategoryCount(c.id) > 0) {
Row() {
Text(c.icon).fontSize(18).width(28)
Text(c.name).fontSize(14).fontColor('#666666').width(50)
// 条形图
Row() {
Text('').height(16)
.width(((this.getCategoryCount(c.id) / this.total) * 100) + '%')
.backgroundColor(c.color).borderRadius(4)
}
.width('100%').backgroundColor('#F0F0F0').borderRadius(4)
.layoutWeight(1).margin({ left: 4, right: 4 })
Text(this.getCategoryCount(c.id) + '个')
.fontSize(13).fontColor('#999999').width(36).textAlign(TextAlign.End)
}.width('100%').margin({ bottom: 8 })
}
}, (c: EventCategory) => c.id)
与前两个项目的条形图对比:
| 项目 | 条形图含义 | 颜色来源 |
|---|---|---|
| 心情日记 | 心情分布次数 | 心情预设色 |
| 习惯打卡 | 习惯完成率 | 习惯主题色 |
| 纪念日管家 | 分类数量分布 | 分类预设色 |
1.4 重置数据
clearData(): void {
AppStorage.set<AnniversaryEvent[]>('events', []);
this.loadData();
}
二、三项目全景对比
至此,我们已经用相同的技术栈完成了三个完整项目。让我们从多个维度进行横向对比。
2.1 核心实体对比
| 维度 | 心情日记 | 习惯打卡 | 纪念日管家 |
|---|---|---|---|
| App名称 | 心情日记 | 习惯打卡 | 纪念日管家 |
| 核心实体 | DiaryEntry | Habit + CheckIn | AnniversaryEvent |
| 实体数量 | 1个 | 2个 | 1个 + 7个预设分类 |
| 日期格式 | YYYY-MM-DD | YYYY-MM-DD | MM-DD |
| AppStorage key | 1个 | 2个 | 1个 |
2.2 页面功能对比
| 功能 | 心情日记 | 习惯打卡 | 纪念日管家 |
|---|---|---|---|
| 首页 | 今日心情+最近日记 | 今日进度+打卡列表 | 今日事件+即将到来 |
| 新增页 | 写日记(表单) | 新建习惯(表单) | 添加纪念日(表单) |
| 列表页 | — | — | 分类筛选+滑动删除 |
| 日历页 | 心情Emoji月历 | 颜色密度热力图 | — |
| 详情页 | — | — | 倒计时+备注编辑 |
| 统计页 | 心情分布+7天趋势 | 完成率排行 | — |
| 个人中心 | 统计+标签云 | 习惯管理+删除 | 分类统计+条形图 |
2.3 核心算法对比
| 算法 | 心情日记 | 习惯打卡 | 纪念日管家 |
|---|---|---|---|
| 名称 | 连续签到 | 连续打卡(Streak) | 跨年倒计时 |
| 方向 | 从今天往前 | 从今天往前 | 从今天到未来 |
| 输入 | all dates | all dates per habit | date(MM-DD) + startYear |
| 输出 | 连续天数 | 连续天数 | 剩余天数 + 第N年 |
| 复杂度 | O(days×n) | O(days×n) | O(1) |
| 边界 | 断签 | 断签 | 跨年 |
2.4 交互方式对比
| 交互 | 心情日记 | 习惯打卡 | 纪念日管家 |
|---|---|---|---|
| 核心交互 | 填写表单→保存 | 点击Toggle打卡/取消 | 滑动删除 |
| 导航方式 | router.push | router.push | router.push(+params) |
| 状态反馈 | 条件渲染if/else | 颜色+删除线+图标 | 大号数字+颜色 |
| 空状态 | 文字提示 | 文字提示 | 图标+文字 |
2.5 @Builder 复用对比
| @Builder | 心情日记 | 习惯打卡 | 纪念日管家 |
|---|---|---|---|
| 卡片模式 | quickBtn | overviewCard, quickAction | qBtn, cBox |
| 列表模式 | diaryRow | habitCheckRow | eventCard, eventRow |
| 菜单模式 | — | menuItem | mItem |
| 其他 | — | — | catChip, infoRow, delBtn |
2.6 数据流对比
心情日记(单模型)
AppStorage.set('entries', list)
→ Index.onPageShow → loadData → calcStats
习惯打卡(双模型)
AppStorage.set('habits', habitList)
AppStorage.set('checkIns', checkInList)
→ Index.onPageShow → loadData → calcToday
纪念日管家(单模型+路由参数)
AppStorage.set('events', eventList)
→ ListPage.onPageShow → loadData → applyFilter
→ DetailPage.aboutToAppear → router.getParams → 匹配事件
三、技术栈全景总结
3.1 通用技术能力
三个项目共用的技术点:
// 1. Stage 模型入口
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage) {
windowStage.loadContent('pages/Index', (err) => { });
}
}
// 2. AppStorage 状态管理
AppStorage.get<T>('key');
AppStorage.set<T>('key', value);
// 3. router 导航
import router from '@ohos.router';
router.pushUrl({ url: 'pages/XXX' });
router.back();
// 4. @State 响应式 + @Builder 复用
@State data: Type = defaultValue;
@Builder reusableUI(param: Type) { }
// 5. 页面生命周期
aboutToAppear(): void { this.loadData(); }
onPageShow(): void { this.loadData(); }
// 6. ArkTS 严格模式
let item: Type = { ... }; // 显式类型
let arr: Type[] = [ ... ]; // 声明类型数组
3.2 各项目独特技术
| 技术点 | 心情日记 | 习惯打卡 | 纪念日管家 |
|---|---|---|---|
| Grid 3列心情选择器 | ✅ | — | — |
| Grid 7列日历 | ✅ | ✅ | — |
| Grid 6列图标选择 | — | ✅ | — |
| Grid 4列分类选择 | — | — | ✅ |
| swipeAction 滑动 | — | — | ✅ |
| 路由参数传递 | — | — | ✅ |
| 双模型级联删除 | — | ✅ | — |
| 颜色热力图 | — | ✅ | — |
| 水平柱状图 | ✅ | ✅ | ✅ |
3.3 代码量估算
| 统计项 | 心情日记 | 习惯打卡 | 纪念日管家 |
|---|---|---|---|
| 页面数 | 5 | 5 | 5 |
| 模型文件 | 1 | 1 | 1 |
| 总行数(估算) | ~800 | ~1000 | ~900 |
| @Builder数量 | 5 | 7 | 8 |
| 状态变量总数 | 27 | 30 | 25 |
四、编码规范三项目通用准则
4.1 导入规范
// ✅ 统一从 @ohos.router 导入
import router from '@ohos.router';
// API 23 下不可用:
// import router from '@kit.AbilityKit'; // ❌
4.2 生命周期规范
// ✅ 每个页面统一模式
aboutToAppear(): void { this.loadData(); }
onPageShow(): void { this.loadData(); }
loadData(): void {
// 1. 从 AppStorage 读取
// 2. 更新 @State
// 3. 执行计算
}
4.3 数据持久化规范
// 首次加载时填充模拟数据
let stored = AppStorage.get<Type[]>('key');
if (stored) {
this.data = stored;
} else {
this.data = getSampleData();
AppStorage.set<Type[]>('key', this.data);
}
4.4 空状态规范
if (this.list.length === 0) {
Column() {
Text('友好提示').fontSize(15).fontColor('#CCCCCC')
}.width('100%').height(120)
.justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)
}
五、写在最后:15篇博文的完整路线图
5.1 三个项目 × 五篇文章
| 项目 | 一:起航 | 二:数据 | 三:UI | 四:交互 | 五:打磨 |
|---|---|---|---|---|---|
| 心情日记 | Stage模型+路由 | AppStorage+枚举 | 首页卡片+写日记 | 日历+统计图 | 标签云+总结 |
| 习惯打卡 | 双模型架构 | Habit+CheckIn | Toggle打卡 | 热力图+柱状图 | 级联删除+对比 |
| 纪念日管家 | 分类系统 | 倒计时算法 | 筛选列表+表单 | swipe+详情页 | 三项目全景对比 |
5.2 你学到的关键技术
你应该已经掌握:
✅ Stage 模型 + ArkTS 声明式 UI
✅ AppStorage 全局状态管理
✅ @ohos.router 页面导航(含参数)
✅ @Builder 组件复用(3种模式)
✅ Grid / List / Row / Column 布局
✅ 生命周期管理(aboutToAppear / onPageShow)
✅ 枚举、接口、工具函数的封装
✅ 倒计时 / 连续签到 / Streak 算法
✅ 颜色热力图 / 柱状图 / 进度条
✅ 滑动删除 / Toggle / 条件渲染
✅ 模拟数据设计
✅ ArkTS 严格模式编码规范
6.3 下一步可以做什么?
- 数据持久化:改用 PersistentStorage 或 RDB
- 动画效果:使用 animateTo 增加过渡动画
- 推送通知:使用 @ohos.notification 发送提醒
- 云同步:接入华为云实现多设备同步
- 暗黑模式:适配深色主题资源
- 国际化:支持中英文切换

感谢你一路跟随这三个项目的开发过程!希望这 15 篇文章能为你学习鸿蒙原生开发提供切实的帮助。
如果你有任何问题或建议,欢迎在评论区留言交流!
Happy Coding! 🚀
更多推荐

所有评论(0)