第12篇:综合实战——制作鸿蒙应用 鸿蒙中文编程
本文介绍了鸿蒙应用开发的综合实战教程,目标是运用前11篇所学知识完成一个完整的应用。提供了三个可选项目:待办事项管理、天气预报和简易社交应用。重点展示了待办事项管理应用的开发过程,包括需求分析、界面设计和完整代码实现。该应用具备添加/编辑事项、标记完成状态、分类筛选、优先级设置和本地存储等功能。代码采用TypeScript编写,包含数据定义、状态管理、UI组件构建等完整实现,可直接运行。通过这个实
·
第12篇:综合实战——制作鸿蒙应用
本课目标:综合运用所学知识,完成一个完整的鸿蒙应用
**作者:**中文编程倡导者—— 李金雨
预计课时:6课时(270分钟)
难度等级:⭐⭐⭐⭐⭐(专家级)
一、开篇引入
1.1 回顾所学知识
经过前面11篇的学习,我们已经掌握了:
| 篇目 | 核心技能 |
|---|---|
| 第1篇 | 搭建开发环境,创建第一个应用 |
| 第2篇 | 数据类型,变量和常量 |
| 第3篇 | 界面组件,布局排版 |
| 第4篇 | 状态管理,事件处理 |
| 第5篇 | 列表渲染,数据展示 |
| 第6篇 | 条件渲染,动态界面 |
| 第7篇 | 功能定义,代码封装 |
| 第8篇 | 组件化开发,复用组件 |
| 第9篇 | 页面跳转,多页面应用 |
| 第10篇 | 网络请求,获取数据 |
| 第11篇 | 本地存储,数据持久化 |
1.2 综合实战目标
今天我们要用所有学到的知识,完成一个完整的应用!
项目选择(三选一):
- 待办事项管理应用 - 任务管理
- 天气预报应用 - 信息展示
- 简易社交应用 - 内容发布
1.3 开发流程
1. 需求分析
↓
2. 界面设计(画草图)
↓
3. 数据结构定义
↓
4. 组件拆分
↓
5. 逐个实现功能
↓
6. 联调测试
↓
7. 优化完善
二、项目A:待办事项管理应用
2.1 需求分析
功能需求:
- ✅ 添加待办事项
- ✅ 标记完成/未完成
- ✅ 删除事项
- ✅ 本地存储(重启不丢失)
- ✅ 分类筛选(全部/未完成/已完成)
- ✅ 优先级设置
- ✅ 截止日期
页面设计:
首页:
┌─────────────────────────┐
│ 📋 待办事项 [+] │
├─────────────────────────┤
│ [全部] [未完成] [已完成] │
├─────────────────────────┤
│ ☑️ 完成的事项 │
│ ☐ 未完成的事项 🗑️ │
│ ☐ 高优先级事项 📅明天 │
│ ... │
│ │
│ 剩余3项待完成 │
└─────────────────────────┘
添加/编辑页:
┌─────────────────────────┐
│ < 返回 保存 │
├─────────────────────────┤
│ 标题:_______________ │
│ │
│ 优先级:[高] [中] [低] │
│ │
│ 截止日期:2024-01-20 │
│ │
│ 备注: │
│ ┌─────────────────┐ │
│ │ │ │
│ │ │ │
│ └─────────────────┘ │
└─────────────────────────┘
2.2 完整代码
import dataPreferences from '@ohos.data.preferences'
import router from '@ohos.router'
// ========== 数据类型定义 ==========
interface 待办事项 {
id: string
标题: string
是否完成: boolean
优先级: string // 高、中、低
截止日期: string
备注: string
创建时间: string
}
// ========== 首页组件 ==========
// 完整可运行代码,复制到 Index.ets 即可运行
@Entry
@Component
struct Index {
@State 待办列表: 待办事项[] = []
@State 当前筛选: string = "全部" // 全部、未完成、已完成
@State 加载中: boolean = true
private 首选项: dataPreferences.Preferences = null
private readonly 存储键: string = 'todos'
async aboutToAppear() {
this.首选项 = await dataPreferences.getPreferences(getContext(this), 'todoApp')
await this.加载数据()
}
async 加载数据() {
this.加载中 = true
let 数据 = await this.首选项.get(this.存储键, '[]') as string
this.待办列表 = JSON.parse(数据)
this.加载中 = false
}
async 保存数据() {
await this.首选项.put(this.存储键, JSON.stringify(this.待办列表))
await this.首选项.flush()
}
build() {
Column() {
// 标题栏
this.标题栏()
// 筛选标签
this.筛选栏()
// 待办列表
this.待办列表区域()
// 统计信息
this.统计栏()
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
// 标题栏
@Builder
标题栏() {
Row() {
Column({ space: 5 }) {
Text('📋 待办事项')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Text(`${this.未完成数量}项待完成`)
.fontSize(12)
.fontColor('#999999')
}
.alignItems(HorizontalAlign.Start)
Button('+', { type: ButtonType.Circle })
.width(50)
.height(50)
.fontSize(30)
.backgroundColor('#4CAF50')
.onClick(() => {
router.pushUrl({
url: 'pages/编辑页',
params: { 模式: '新建' }
})
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding(20)
.backgroundColor('#FFFFFF')
}
// 筛选栏
@Builder
筛选栏() {
Row({ space: 15 }) {
ForEach(['全部', '未完成', '已完成'], (筛选: string) => {
Text(筛选)
.fontSize(14)
.fontColor(this.当前筛选 == 筛选 ? '#FFFFFF' : '#666666')
.padding({ left: 15, right: 15, top: 6, bottom: 6 })
.backgroundColor(this.当前筛选 == 筛选 ? '#2196F3' : '#F5F5F5')
.borderRadius(15)
.onClick(() => {
this.当前筛选 = 筛选
})
})
}
.width('100%')
.padding(15)
.backgroundColor('#FFFFFF')
}
// 待办列表区域
@Builder
待办列表区域() {
if (this.加载中) {
Column({ space: 10 }) {
LoadingProgress()
.width(40)
.height(40)
Text('加载中...')
.fontColor('#999999')
}
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
} else if (this.过滤后列表.length == 0) {
Column({ space: 15 }) {
Text('📭')
.fontSize(80)
Text(this.当前筛选 == '全部' ? '还没有待办事项' : `没有${this.当前筛选}的事项`)
.fontSize(16)
.fontColor('#999999')
Text('点击右上角+添加')
.fontSize(14)
.fontColor('#CCCCCC')
}
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
} else {
List({ space: 10 }) {
ForEach(this.过滤后列表, (事项: 待办事项) => {
ListItem() {
this.待办卡片(事项)
}
.swipeAction({
end: {
Button('删除')
.width(80)
.height('100%')
.backgroundColor('#F44336')
.fontColor('#FFFFFF')
.onClick(() => this.删除事项(事项.id))
}
})
})
}
.padding(15)
.layoutWeight(1)
}
}
// 待办卡片
@Builder
待办卡片(事项: 待办事项) {
Row({ space: 12 }) {
// 完成状态复选框
Text(事项.是否完成 ? '☑️' : '⬜')
.fontSize(24)
.onClick(() => this.切换完成状态(事项.id))
// 内容区域
Column({ space: 5 }) {
Row({ space: 8 }) {
Text(事项.标题 || '无标题')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor(事项.是否完成 ? '#999999' : '#333333')
.decoration({
type: 事项.是否完成 ? TextDecorationType.LineThrough : TextDecorationType.None
})
.layoutWeight(1)
// 优先级标签
Text(事项.优先级)
.fontSize(10)
.fontColor('#FFFFFF')
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.backgroundColor(this.获取优先级颜色(事项.优先级))
.borderRadius(4)
}
.width('100%')
// 截止日期
if (事项.截止日期) {
Row({ space: 5 }) {
Text('📅')
.fontSize(12)
Text(事项.截止日期)
.fontSize(12)
.fontColor(this.是否过期(事项.截止日期) ? '#F44336' : '#999999')
if (this.是否过期(事项.截止日期) && !事项.是否完成) {
Text('已过期')
.fontSize(10)
.fontColor('#F44336')
}
}
}
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
// 编辑按钮
Text('✏️')
.fontSize(18)
.onClick(() => {
router.pushUrl({
url: 'pages/编辑页',
params: { 模式: '编辑', 事项: JSON.stringify(事项) }
})
})
}
.width('100%')
.padding(15)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 4, color: '#10000000' })
}
// 统计栏
@Builder
统计栏() {
Row({ space: 20 }) {
this.统计项('总任务', this.待办列表.length)
this.统计项('待完成', this.未完成数量)
this.统计项('已完成', this.已完成数量)
}
.width('100%')
.justifyContent(FlexAlign.Center)
.padding(15)
.backgroundColor('#FFFFFF')
.border({ width: { top: 1 }, color: '#EEEEEE' })
}
@Builder
统计项(标签: string, 数值: number) {
Column({ space: 5 }) {
Text(`${数值}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#2196F3')
Text(标签)
.fontSize(12)
.fontColor('#999999')
}
}
// 计算属性
get 过滤后列表(): 待办事项[] {
switch (this.当前筛选) {
case '未完成':
return this.待办列表.filter(事项 => !事项.是否完成)
case '已完成':
return this.待办列表.filter(事项 => 事项.是否完成)
default:
return this.待办列表
}
}
get 未完成数量(): number {
return this.待办列表.filter(事项 => !事项.是否完成).length
}
get 已完成数量(): number {
return this.待办列表.filter(事项 => 事项.是否完成).length
}
// 方法
async 切换完成状态(id: string) {
let 索引 = this.待办列表.findIndex(事项 => 事项.id == id)
if (索引 != -1) {
this.待办列表[索引].是否完成 = !this.待办列表[索引].是否完成
this.待办列表 = [...this.待办列表]
await this.保存数据()
}
}
async 删除事项(id: string) {
this.待办列表 = this.待办列表.filter(事项 => 事项.id != id)
await this.保存数据()
}
获取优先级颜色(优先级: string): string {
switch (优先级) {
case '高': return '#F44336'
case '中': return '#FF9800'
case '低': return '#4CAF50'
default: return '#9E9E9E'
}
}
是否过期(日期字符串: string): boolean {
let 截止日期 = new Date(日期字符串)
let 今天 = new Date()
今天.setHours(0, 0, 0, 0)
return 截止日期 < 今天
}
onPageShow() {
// 从编辑页返回时刷新数据
this.加载数据()
}
}
// ========== 编辑页组件 ==========
// 完整可运行代码,复制到 Index.ets 即可运行
@Entry
@Component
struct Index {
@State 模式: string = '新建'
@State 标题: string = ''
@State 优先级: string = '中'
@State 截止日期: string = ''
@State 备注: string = ''
@State 编辑ID: string = ''
private 首选项: dataPreferences.Preferences = null
async aboutToAppear() {
this.首选项 = await dataPreferences.getPreferences(getContext(this), 'todoApp')
// 获取传递的参数
let 参数 = router.getParams()
if (参数) {
this.模式 = 参数['模式'] as string
if (this.模式 == '编辑' && 参数['事项']) {
let 事项 = JSON.parse(参数['事项'] as string)
this.编辑ID = 事项.id
this.标题 = 事项.标题
this.优先级 = 事项.优先级
this.截止日期 = 事项.截止日期
this.备注 = 事项.备注
}
}
}
build() {
Column({ space: 20 }) {
// 标题栏
Row() {
Text('< 返回')
.fontSize(16)
.fontColor('#666666')
.onClick(() => router.back())
Text(this.模式 == '新建' ? '新建待办' : '编辑待办')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text('保存')
.fontSize(16)
.fontColor(this.可以保存 ? '#4CAF50' : '#CCCCCC')
.onClick(() => {
if (this.可以保存) {
this.保存()
}
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding(20)
.backgroundColor('#FFFFFF')
// 表单内容
Scroll() {
Column({ space: 20 }) {
// 标题输入
this.表单项('标题') {
TextInput({ placeholder: '请输入标题', text: this.标题 })
.width('100%')
.height(50)
.backgroundColor('#F5F5F5')
.borderRadius(8)
.onChange((值) => this.标题 = 值)
}
// 优先级选择
this.表单项('优先级') {
Row({ space: 10 }) {
ForEach(['高', '中', '低'], (优先级: string) => {
Text(优先级)
.fontSize(14)
.fontColor(this.优先级 == 优先级 ? '#FFFFFF' : '#666666')
.padding({ left: 20, right: 20, top: 8, bottom: 8 })
.backgroundColor(
this.优先级 == 优先级
? this.获取优先级颜色(优先级)
: '#F5F5F5'
)
.borderRadius(20)
.onClick(() => this.优先级 = 优先级)
})
}
}
// 截止日期
this.表单项('截止日期') {
TextInput({ placeholder: '选择日期,如:2024-01-20', text: this.截止日期 })
.width('100%')
.height(50)
.backgroundColor('#F5F5F5')
.borderRadius(8)
.onChange((值) => this.截止日期 = 值)
}
// 备注
this.表单项('备注') {
TextArea({ placeholder: '添加备注...', text: this.备注 })
.width('100%')
.height(150)
.backgroundColor('#F5F5F5')
.borderRadius(8)
.onChange((值) => this.备注 = 值)
}
}
.width('100%')
.padding(20)
}
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
@Builder
表单项(标签: string, 内容: () => void) {
Column({ space: 8 }) {
Text(标签)
.fontSize(14)
.fontColor('#666666')
.alignSelf(ItemAlign.Start)
content()
}
.width('100%')
}
get 可以保存(): boolean {
return this.标题.trim() != ''
}
获取优先级颜色(优先级: string): string {
switch (优先级) {
case '高': return '#F44336'
case '中': return '#FF9800'
case '低': return '#4CAF50'
default: return '#9E9E9E'
}
}
async 保存() {
let 列表数据 = await this.首选项.get('todos', '[]') as string
let 列表: 待办事项[] = JSON.parse(列表数据)
if (this.模式 == '新建') {
// 添加新事项
let 新事项: 待办事项 = {
id: Date.now().toString(),
标题: this.标题.trim(),
是否完成: false,
优先级: this.优先级,
截止日期: this.截止日期,
备注: this.备注,
创建时间: new Date().toISOString()
}
列表.unshift(新事项)
} else {
// 更新现有事项
let 索引 = 列表.findIndex(事项 => 事项.id == this.编辑ID)
if (索引 != -1) {
列表[索引].标题 = this.标题.trim()
列表[索引].优先级 = this.优先级
列表[索引].截止日期 = this.截止日期
列表[索引].备注 = this.备注
}
}
await this.首选项.put('todos', JSON.stringify(列表))
await this.首选项.flush()
router.back()
}
}
三、项目总结
3.1 用到的知识点
| 知识点 | 应用场景 |
|---|---|
| @State | 管理待办列表、筛选状态 |
| @Component | 封装待办卡片、统计项 |
| List/ForEach | 展示待办列表 |
| if-else | 根据筛选条件显示不同内容 |
| 本地存储 | 保存待办数据 |
| 页面跳转 | 首页和编辑页之间跳转 |
| 计算属性 | 统计待完成/已完成数量 |
| 滑动删除 | 左滑删除待办 |
3.2 项目亮点
- 完整的数据流:添加→存储→读取→展示→编辑→更新
- 友好的交互:滑动删除、优先级标签、过期提醒
- 数据持久化:重启应用数据不丢失
- 筛选功能:快速查看不同状态的事项
- 统计信息:一目了然了解任务完成情况
3.3 扩展建议
可以尝试添加以下功能:
- 🔍 搜索功能
- 🏷️ 标签分类
- 🔔 提醒通知
- 📊 完成统计图表
- ☁️ 云端同步
四、课程总结
4.1 学习路径回顾
入门阶段(1-3篇)
├── 搭建环境
├── 学习基础语法
└── 掌握界面组件
进阶阶段(4-7篇)
├── 状态管理
├── 列表渲染
├── 条件渲染
└── 功能封装
高级阶段(8-11篇)
├── 组件化开发
├── 页面路由
├── 网络请求
└── 本地存储
实战阶段(12篇)
└── 综合项目
4.2 核心技能清单
基础技能:
- ✅ 搭建鸿蒙开发环境
- ✅ 使用ArkTS编写代码
- ✅ 使用中文命名变量、组件
- ✅ 理解数据类型和变量
界面开发:
- ✅ 使用基础组件(Text、Button、Image等)
- ✅ 使用布局容器(Column、Row、List等)
- ✅ 设置样式(颜色、大小、间距等)
- ✅ 响应式界面(状态管理)
数据处理:
- ✅ 定义和使用数据类型
- ✅ 列表渲染和条件渲染
- ✅ 封装功能函数
- ✅ 创建可复用组件
高级功能:
- ✅ 多页面应用开发
- ✅ 页面间跳转和传参
- ✅ 网络请求获取数据
- ✅ 本地数据存储
4.3 继续学习建议
深入学习:
- 鸿蒙官方文档:https://developer.harmonyos.com/
- ArkTS高级特性
- 动画和过渡效果
- 性能优化技巧
实践项目:
- 个人博客应用
- 在线商城应用
- 社交聊天应用
- 游戏应用
参与社区:
- 加入鸿蒙开发者社区
- 参与开源项目
- 分享学习心得
五、写在最后
恭喜你完成了全部12篇教程的学习!🎉
从搭建环境到完成实战项目,你已经掌握了鸿蒙应用开发的核心技能。
记住:
- 编程是一门实践性很强的技能,多写代码才能提高
- 遇到问题不要怕,学会查阅文档和搜索解决方案
- 保持好奇心,不断探索新技术
未来可期:
- 你可以开发自己的鸿蒙应用
- 你可以参加鸿蒙开发者大赛
- 你可以成为鸿蒙生态的贡献者
让我们开始你的鸿蒙开发之旅吧! 🚀
本教程由李金雨编写
联系邮箱:wbtm2718@qq.com
更多推荐

所有评论(0)