项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
在上一部分中,我们介绍了任务列表的基础结构、数据模型设计以及外层Column的实现。本教程将继续深入探讨TaskItem组件的内部结构,包括Row布局的实现、条件渲染的使用以及交互事件的处理,帮助开发者掌握更复杂的布局和交互技巧,创建功能丰富、用户体验良好的任务列表界面。
@Component
struct TaskItem {
@Prop task: string
@State showActions: boolean = false
build() {
// 组件内容
}
}
装饰器 | 属性 | 类型 | 初始值 | 说明 |
---|---|---|---|---|
@Component | - | - | - | 标识这是一个自定义组件 |
@Prop | task | string | - | 从父组件接收的任务文本,只读属性 |
@State | showActions | boolean | false | 组件内部状态,控制操作按钮的显示与隐藏 |
@Component装饰器用于定义自定义组件,它告诉框架这是一个可复用的UI组件,具有自己的生命周期和渲染逻辑。
@Prop装饰器用于定义从父组件接收的属性,特点包括:
@State装饰器用于定义组件的内部状态,特点包括:
在TaskItem组件中,我们使用@State装饰器定义了showActions状态,用于控制操作按钮的显示与隐藏,初始值为false(隐藏状态)。
Row({ space: 16 })
{
// 任务内容(垂直排列)
Column({ space: 4 }) {
// 文本组件
}
// 操作按钮(水平排列,悬停显示)
if (this.showActions) {
Row({ space: 8 }) {
// 按钮组件
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
}
}
.width('100%')
.padding({ left: 12,right:12, top: 16, bottom: 16 })
.backgroundColor(0xFFFFFF)
.borderRadius(8)
.shadow({ radius: 2, color: 0x05000000 })
.onHover((isHover: boolean, event: HoverEvent)=>{
// 悬停事件处理
})
每个任务项使用Row组件实现水平布局,将任务内容和操作按钮分别放置在左右两侧。
属性/参数 | 值 | 作用 |
---|---|---|
space | 16 | 设置子组件之间的水平间距为16vp |
width | 100% | 设置Row宽度占父容器的100% |
padding | { left: 12,right:12, top: 16, bottom: 16 } | 设置内边距,上下16vp,左右12vp |
backgroundColor | 0xFFFFFF | 设置背景色为白色 |
borderRadius | 8 | 设置边框圆角为8vp |
shadow | { radius: 2, color: 0x05000000 } | 设置阴影效果,营造卡片视觉 |
.backgroundColor(0xFFFFFF)
.borderRadius(8)
.shadow({ radius: 2, color: 0x05000000 })
这三个属性的组合实现了卡片式设计:
阴影参数解析:
参数 | 值 | 说明 |
---|---|---|
radius | 2 | 阴影扩散半径,值越大阴影越模糊 |
color | 0x05000000 | 阴影颜色,0x05表示透明度为5%的黑色阴影 |
Column({ space: 4 }) {
Text(this.task)
.fontSize(16)
.fontWeight(500)
Text('2025-05-30 14:00')
.fontSize(12)
.fontColor(0x666666)
}
任务内容区域使用Column组件垂直排列任务标题和日期信息。
属性/参数 | 值 | 作用 |
---|---|---|
space | 4 | 设置子组件之间的垂直间距为4vp |
Text(this.task)
.fontSize(16)
.fontWeight(500)
属性 | 值 | 作用 |
---|---|---|
构造参数 | this.task | 设置文本内容,来自@Prop装饰的task属性 |
fontSize | 16 | 设置字体大小为16vp |
fontWeight | 500 | 设置字体粗细为中等偏粗 |
Text('2025-05-30 14:00')
.fontSize(12)
.fontColor(0x666666)
属性 | 值 | 作用 |
---|---|---|
构造参数 | ‘2025-05-30 14:00’ | 设置文本内容为固定的日期时间文本 |
fontSize | 12 | 设置字体大小为12vp,小于标题字号 |
fontColor | 0x666666 | 设置字体颜色为深灰色,弱化视觉重要性 |
任务内容区域的文本设计遵循了明确的视觉层次:
这种设计使用户能够快速识别重要信息,同时在需要时也能获取次要信息,提高了界面的可读性和信息层次感。
if (this.showActions) {
Row({ space: 8 }) {
Button('编辑')
.width(48)
.height(28)
.fontSize(12)
.backgroundColor(0xE0F5FF)
.fontColor(0x007DFF)
Button('删除')
.width(48)
.height(28)
.fontSize(12)
.backgroundColor(0xFFF0F0)
.fontColor(0xFF4D4F53)
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
}
条件渲染使用if语句实现,只有当showActions为true时,才会渲染操作按钮区域。
属性/参数 | 值 | 作用 |
---|---|---|
space | 8 | 设置按钮之间的水平间距为8vp |
alignItems | VerticalAlign.Center | 设置子组件在垂直方向上居中对齐 |
justifyContent | FlexAlign.Center | 设置子组件在水平方向上居中对齐 |
Button('编辑')
.width(48)
.height(28)
.fontSize(12)
.backgroundColor(0xE0F5FF)
.fontColor(0x007DFF)
属性 | 值 | 作用 |
---|---|---|
构造参数 | ‘编辑’ | 设置按钮文本 |
width | 48 | 设置按钮宽度为48vp |
height | 28 | 设置按钮高度为28vp |
fontSize | 12 | 设置字体大小为12vp |
backgroundColor | 0xE0F5FF | 设置背景色为浅蓝色 |
fontColor | 0x007DFF | 设置文字颜色为蓝色 |
Button('删除')
.width(48)
.height(28)
.fontSize(12)
.backgroundColor(0xFFF0F0)
.fontColor(0xFF4D4F53)
属性 | 值 | 作用 |
---|---|---|
构造参数 | ‘删除’ | 设置按钮文本 |
width | 48 | 设置按钮宽度为48vp |
height | 28 | 设置按钮高度为28vp |
fontSize | 12 | 设置字体大小为12vp |
backgroundColor | 0xFFF0F0 | 设置背景色为浅红色 |
fontColor | 0xFF4D4F53 | 设置文字颜色为红色 |
两个按钮使用了不同的颜色方案来区分不同的操作类型:
这种颜色编码符合用户的心理预期,使界面更加直观易用。
.onHover((isHover: boolean, event: HoverEvent)=>{
if (isHover) {this.showActions = true}else{
this.showActions = false
}
})
onHover事件用于检测鼠标是否悬停在组件上,它接收一个回调函数,该函数有两个参数:
参数 | 类型 | 说明 |
---|---|---|
isHover | boolean | 表示鼠标是否悬停在组件上 |
event | HoverEvent | 包含事件详细信息的对象 |
if (isHover) {this.showActions = true}else{
this.showActions = false
}
这段代码根据悬停状态更新showActions状态变量:
由于showActions是使用@State装饰器定义的响应式状态变量,当其值变化时,框架会自动重新渲染组件,实现操作按钮的动态显示与隐藏。
这种基于悬停的交互设计有以下优势:
让我们回顾完整的TaskItem组件代码:
@Component
struct TaskItem {
@Prop task: string
@State showActions: boolean = false
build() {
Row({ space: 16 })
{
// 任务内容(垂直排列)
Column({ space: 4 }) {
Text(this.task)
.fontSize(16)
.fontWeight(500)
Text('2025-05-30 14:00')
.fontSize(12)
.fontColor(0x666666)
}
// 操作按钮(水平排列,悬停显示)
if (this.showActions) {
Row({ space: 8 }) {
Button('编辑')
.width(48)
.height(28)
.fontSize(12)
.backgroundColor(0xE0F5FF)
.fontColor(0x007DFF)
Button('删除')
.width(48)
.height(28)
.fontSize(12)
.backgroundColor(0xFFF0F0)
.fontColor(0xFF4D4F53)
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
}
}
.width('100%')
.padding({ left: 12,right:12, top: 16, bottom: 16 })
.backgroundColor(0xFFFFFF)
.borderRadius(8)
.shadow({ radius: 2, color: 0x05000000 })
.onHover((isHover: boolean, event: HoverEvent)=>{
if (isHover) {this.showActions = true}else{
this.showActions = false
}
}) // 鼠标悬停显示操作按钮
}
}
本案例展示了多层嵌套布局的实现方式:
这种多层嵌套的布局结构能够实现复杂的界面设计,同时保持代码的清晰和可维护性。
通过本教程的两个部分,我们详细讲解了如何使用Column和Row组件的嵌套组合,结合自定义组件和条件渲染,创建一个交互式任务列表