目录
[第三步:编写第一个组件 - 待办列表页](#第三步:编写第一个组件 - 待办列表页)
引言
在鸿蒙生态的应用开发中,ArkTS 无疑是当下的主角。它基于广受欢迎的 TypeScript,并融入了声明式UI、状态管理等现代化特性,让应用开发变得更高效、更可靠。
如果你是一名前端或移动端开发者,对 React、Vue、SwiftUI 或 Jetpack Compose 有所了解,那么 ArkTS 会让你感到非常亲切。如果你是完全的新手,也不必担心,ArkTS 的语法清晰直观。
本篇博客将带你从环境搭建开始,一步步构建一个简单的待办事项(Todo)应用,在实践中掌握 ArkTS 的核心概念。
第一步:准备工作
1. 开发环境搭建
-
下载 DevEco Studio :访问 华为开发者官网,下载并安装最新的 DevEco Studio。这是官方的集成开发环境,必不可少。
-
配置 SDK 与工具:启动 DevEco Studio,按照向导安装 HarmonyOS SDK 和必要的构建工具(如 OpenJDK)。
-
注册开发者账号:你需要一个华为开发者账号,用于真机调试和应用发布。
2. 创建新项目
-
打开 DevEco Studio,选择 "Create Project"。
-
我们选择最通用的 "Empty Ability" 模板,点击 "Next"。
-
在项目配置页面:
-
Project Name :
MyFirstTodoApp -
Bundle Name : 按默认或自定义,如
com.example.mytodo -
Save Location: 选择你的项目存放路径
-
Compile API Version: 选择最新的稳定版本
-
Model : 选择
Stage模型(这是鸿蒙推荐的应用模型) -
Language : 确保选择
ArkTS -
Enable Super Visual : 暂时不勾选,我们先从纯代码开始
-
-
点击 "Finish",等待项目初始化完成。
第二步:理解项目结构
项目创建好后,你会看到类似下面的目录结构,我们重点关注几个核心文件和文件夹:
MyFirstTodoApp/
├── entry/ # 主模块
│ ├── src/
│ │ ├── main/
│ │ │ ├── ets/ // ArkTS 代码目录
│ │ │ │ ├── entryability/
│ │ │ │ │ └── EntryAbility.ts // 应用入口能力
│ │ │ │ ├── pages/
│ │ │ │ │ └── Index.ets // 应用首页!!!
│ │ │ │ └── ...
│ │ │ ├── resources/ // 资源文件(图片,字符串等)
│ │ │ └── module.json5 // 模块配置文件
│ │ └── ...
├── ...
-
EntryAbility.ts:应用的启动入口,负责应用的生命周期。 -
Index.ets:这是我们今天的主战场,应用的第一个页面。 -
module.json5:配置页面路由、权限等信息。
第三步:编写第一个组件 - 待办列表页
现在,我们打开 Index.ets 文件,清空内容,开始编码。
1. 搭建UI骨架:标题与列表区域
我们先构建一个最基础的UI,包含一个标题和一个(还未有数据的)列表。
// Index.ets
@Entry // @Entry 装饰器表示这是应用的入口页面
@Component // @Component 装饰器表示这是一个自定义组件
struct Index {
// @State 装饰器表示这个变量是组件的状态数据,它的变化会触发UI重新渲染
@State message: string = '我的待办清单'
build() {
// build() 方法是UI的描述方法,必须被实现
Column() { // Column 是垂直布局容器
Text(this.message) // Text 组件用于显示文本
.fontSize(30) // 链式调用,设置样式
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
List() { // List 组件用于创建可滚动列表
// 稍后我们会在这里添加列表项
}
.layoutWeight(1) // 占据剩余所有空间
.width('100%')
}
.width('100%')
.height('100%')
.padding(12)
}
}
现在点击运行(可以使用 Previewer 预览器或连接真机),你应该能看到一个带有 "我的待办清单" 标题的页面。
2. 定义数据模型与状态
一个待办项通常包含内容和完成状态。我们来定义它。
// 在 @Component struct Index 外部,定义待办项的数据模型
class TodoItem {
id: number
content: string
isCompleted: boolean
constructor(id: number, content: string, isCompleted: boolean = false) {
this.id = id
this.content = content
this.isCompleted = isCompleted
}
}
@Entry
@Component
struct Index {
@State message: string = '我的待办清单'
// 定义状态数据:待办列表,初始为空数组
@State todoList: TodoItem[] = []
// 组件的 aboutToAppear 生命周期回调,在组件即将出现时触发
aboutToAppear() {
// 初始化一些模拟数据
this.todoList.push(new TodoItem(1, '学习 ArkTS 基础', true))
this.todoList.push(new TodoItem(2, '构建一个 Todo 应用'))
this.todoList.push(new TodoItem(3, '发布到应用市场'))
}
build() {
// ... build 方法内容与之前一致 ...
}
}
3. 渲染动态列表
现在,我们用 ForEach 将 todoList 中的数据渲染出来。
// ... 数据模型定义 ...
@Entry
@Component
struct Index {
@State message: string = '我的待办清单'
@State todoList: TodoItem[] = []
aboutToAppear() {
// ... 初始化数据 ...
}
build() {
Column() {
Text(this.message)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
List() {
// ForEach 遍历 todoList 数组,为每个 item 生成一个 ListItem
ForEach(this.todoList, (item: TodoItem) => {
ListItem() {
// 每一行的布局:水平排列的复选框和文本
Row() {
// 复选框,根据状态显示不同符号
Text(item.isCompleted ? '✓' : '○')
.fontSize(20)
.margin({ right: 10 })
.onClick(() => {
// 点击切换完成状态
item.isCompleted = !item.isCompleted
// 由于 @State 装饰器,数组本身的改变会触发UI更新
// 但直接修改 item 属性不会,所以我们需要"通知"状态更新
// 这里使用一个小技巧:重新赋值数组来触发UI刷新
this.todoList = [...this.todoList]
})
Text(item.content)
.fontSize(18)
.decoration({ type: item.isCompleted ? TextDecorationType.LineThrough : TextDecorationType.None })
.opacity(item.isCompleted ? 0.5 : 1.0)
}
.width('100%')
.justifyContent(FlexAlign.Start)
.padding(10)
.backgroundColor('#FFF')
.borderRadius(8)
.margin({ bottom: 8 })
}
}, (item: TodoItem) => item.id.toString()) // 第三个参数是 keyGenerator,用于优化列表渲染
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.padding(12)
.backgroundColor('#F1F2F3')
}
}
现在运行,你应该能看到一个包含三个待办项的列表,并且可以点击前面的圆圈来切换完成状态(显示删除线)。
4. 添加交互:新增待办项
一个不能添加任务的待办列表是不完整的。我们来在顶部添加一个输入框和按钮。
// ... 数据模型定义 ...
@Entry
@Component
struct Index {
@State message: string = '我的待办清单'
@State todoList: TodoItem[] = []
@State newTodoContent: string = '' // 绑定输入框的内容
aboutToAppear() {
// ... 初始化数据 ...
}
// 添加新待办项的方法
addTodoItem() {
if (this.newTodoContent.trim() === '') {
return
}
const newId = this.todoList.length > 0 ? Math.max(...this.todoList.map(i => i.id)) + 1 : 1
this.todoList.push(new TodoItem(newId, this.newTodoContent.trim()))
this.newTodoContent = '' // 清空输入框
this.todoList = [...this.todoList] // 触发UI更新
}
build() {
Column() {
Text(this.message)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 20 })
// 新增:输入行
Row() {
TextInput({ text: this.newTodoContent, placeholder: '输入新任务...' })
.layoutWeight(1) // 输入框占据大部分空间
.onChange((value: string) => {
this.newTodoContent = value // 更新输入框内容的状态
})
Button('添加', { type: ButtonType.Capsule, stateEffect: true })
.backgroundColor('#007DFF')
.fontColor('#FFF')
.onClick(() => {
this.addTodoItem() // 点击按钮调用添加方法
})
}
.width('100%')
.margin({ bottom: 20 })
List() {
// ... ForEach 列表 ...
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.padding(12)
.backgroundColor('#F1F2F3')
}
}
大功告成!现在你已经拥有了一个功能完整的简易待办事项应用:
-
显示待办列表
-
标记任务完成/未完成
-
添加新的待办项
第四步:核心概念回顾与进阶
通过这个简单的应用,我们实践了 ArkTS 最核心的几个概念:
-
声明式UI :我们不是在命令式地操作DOM或View,而是在
build()方法里声明 UI应该长什么样子。UI是状态的函数(UI = f(State))。 -
装饰器:
-
@Entry、@Component定义了组件。 -
@State管理了组件的内部状态,状态变化驱动UI更新。
-
-
组件生命周期 :
aboutToAppear用于初始化数据。 -
状态管理 :我们使用了
@State来管理todoList和newTodoContent。对于更复杂的应用,你可能会用到@Prop(父子组件单向同步)、@Link(双向绑定)或AppStorage(应用全局状态)。
下一步做什么?
这个应用只是一个开始。要让它更完善、更强大,你可以尝试:
-
持久化存储 :使用
@ohos.data.relationalStore将待办列表保存到本地数据库,这样应用重启后数据不会丢失。 -
删除功能:为每个列表项添加一个滑动删除或点击删除按钮。
-
编辑功能:点击任务内容可以进入编辑模式。
-
更多状态:添加"重要"、"分类"等状态。
-
页面路由 :创建第二个页面(如设置页),并使用
router实现页面跳转。
总结
恭喜你!你已经成功地使用 ArkTS 从零构建了一个可交互的鸿蒙应用。这个过程展示了 ArkTS 在构建现代化、高性能应用方面的简洁与强大。
记住学习路径:
-
掌握基础语法(TypeScript + 装饰器)。
-
理解声明式UI与组件化。
-
精通状态管理。
-
集成鸿蒙原生能力(网络、存储、通知等)。
继续探索官方文档和示例,动手构建更复杂的应用,你将成为鸿蒙应用开发的专家!Happy Coding!