HarmonyOS应用开发实战:萌宠日记 - 健康提醒列表与动态数据绑定

前言

健康提醒列表萌宠日记 首页底部的重要功能模块,它展示宠物即将到来的 驱虫、疫苗、体检 等健康事项。通过 ForEach 动态渲染 数据列表,每个提醒项包含 图标、标题、日期、倒计时 等要素,用户可以一目了然地掌握宠物的健康管理状态。

本文将从 萌宠日记 的健康提醒列表实现出发,深入解析 ForEach 动态渲染、列表项布局、数据绑定、以及交互反馈的设计。

一、健康提醒列表整体设计

1.1 数据模型

typescript 复制代码
// HomePage.ets --- 健康提醒数据结构
interface HealthReminder {
  icon: string     // 图标(Emoji)
  title: string    // 提醒标题
  date: string     // 提醒日期
  daysLeft: string // 倒计时文字
  color: string    // 图标背景色
}

private healthReminders: HealthReminder[] = [
  {
    icon: '🛡️',
    title: '驱虫',
    date: '2024.05.20',
    daysLeft: '还有15天',
    color: '#FFF3E0'
  }
]

1.2 列表渲染

typescript 复制代码
// 健康提醒区域
Column({ space: 12 }) {
  // 标题行
  Row() {
    Text('健康提醒')
      .fontSize(16)
      .fontWeight(FontWeight.Bold)
      .fontColor('#333333')
    Blank()
    Text('+')
      .fontSize(24)
      .fontColor('#F5A623')
  }
  .width('100%')

  // 列表项
  ForEach(this.healthReminders, (reminder: HealthReminder) => {
    Row({ space: 12 }) {
      // 图标
      Column() {
        Text(reminder.icon).fontSize(24)
      }
      .width(44).height(44)
      .backgroundColor(reminder.color)
      .borderRadius(12)
      .justifyContent(FlexAlign.Center)

      // 标题和日期
      Column({ space: 4 }) {
        Text(reminder.title)
          .fontSize(14)
          .fontWeight(FontWeight.Medium)
          .fontColor('#333333')
        Text(reminder.date)
          .fontSize(12)
          .fontColor('#999999')
      }
      .alignItems(HorizontalAlign.Start)

      Blank()

      // 倒计时
      Text(reminder.daysLeft)
        .fontSize(12)
        .fontColor('#F5A623')

      // 右箭头
      Text('›')
        .fontSize(18)
        .fontColor('#CCCCCC')
    }
    .width('100%')
    .padding(12)
    .backgroundColor('#FFFFFF')
    .borderRadius(12)
  })
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 16 })

提示 :健康提醒列表使用 ForEach 动态渲染,数据驱动 UI。当提醒数据发生变化时(如新增、删除、更新倒计时),UI 会自动同步更新,这是 ArkTS 声明式编程的核心优势。

二、列表项布局详解

2.1 每行布局结构

复制代码
┌─────────────────────────────────────────┐
│  ┌────┐  ┌──────────────┐   还有15天  › │
│  │🛡️ │  │ 驱虫         │              │
│  │    │  │ 2024.05.20   │              │
│  └────┘  └──────────────┘              │
└─────────────────────────────────────────┘

2.2 布局分解

位置 组件 内容 说明
左侧 Column 图标 Emoji 44×44vp 圆角容器
左中 Column 标题 + 日期 垂直排列,间距 4vp
右中 Blank 弹性占位 将内容推到两端
右侧 Text 倒计时 橙色文字,引人注意
最右 Text 右箭头,暗示可点击

三、标题行设计

3.1 标题 + 添加按钮

typescript 复制代码
Row() {
  Text('健康提醒')
    .fontSize(16)
    .fontWeight(FontWeight.Bold)
    .fontColor('#333333')
  Blank()
  Text('+')          // 添加按钮
    .fontSize(24)
    .fontColor('#F5A623')
}

3.2 添加按钮交互

typescript 复制代码
Text('+')
  .fontSize(24)
  .fontColor('#F5A623')
  .onClick(() => {
    // 跳转到添加提醒页面
    console.log('Add new reminder')
  })

四、动态数据绑定

4.1 数据驱动 UI

typescript 复制代码
// 数据变化时,UI 自动更新
@State healthReminders: HealthReminder[] = [
  { icon: '🛡️', title: '驱虫', date: '2024.05.20', daysLeft: '还有15天', color: '#FFF3E0' }
]

// 添加新提醒
addReminder(reminder: HealthReminder): void {
  this.healthReminders.push(reminder)
  // @State 装饰的数组变化后,UI 自动重新渲染
}

// 删除提醒
removeReminder(index: number): void {
  this.healthReminders.splice(index, 1)
}

// 更新倒计时
updateDaysLeft(): void {
  this.healthReminders = this.healthReminders.map(item => {
    // 重新计算倒计时
    return { ...item, daysLeft: this.calculateDaysLeft(item.date) }
  })
}

4.2 @State 与数组变化

数组操作 UI 是否更新 说明
push() ✅ 更新 新增元素
splice() ✅ 更新 删除/替换元素
pop() ✅ 更新 移除末尾元素
直接赋值 ✅ 更新 this.arr = newArr
修改元素属性 ⚠️ 需解构 使用 ... 展开运算符创建新对象

五、倒计时计算

5.1 倒计时逻辑

typescript 复制代码
// 计算倒计时
calculateDaysLeft(targetDate: string): string {
  const today = new Date()
  const target = new Date(targetDate)
  const diffTime = target.getTime() - today.getTime()
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))

  if (diffDays > 0) {
    return `还有${diffDays}天`
  } else if (diffDays === 0) {
    return '今天'
  } else {
    return `已过期${Math.abs(diffDays)}天`
  }
}

5.2 倒计时样式

typescript 复制代码
// 根据剩余天数显示不同颜色
getDaysLeftColor(daysLeft: string): string {
  if (daysLeft.includes('今天')) {
    return '#F44336'  // 红色 --- 紧急
  } else if (daysLeft.includes('已过期')) {
    return '#F44336'  // 红色 --- 已过期
  } else {
    return '#F5A623'  // 橙色 --- 正常
  }
}

六、列表项交互

6.1 点击事件

typescript 复制代码
Row({ space: 12 }) {
  // 列表项内容...
}
.width('100%')
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.onClick(() => {
  // 跳转到提醒详情/编辑页
  console.log('Reminder clicked:', reminder.title)
})

6.2 完整交互设计

交互元素 行为 实现
列表项 点击跳转详情 onClick
添加按钮 跳转添加页 onClick
右箭头 视觉提示可点击 Text('›')
倒计时 状态指示 颜色变化

七、ForEach 渲染优化

7.1 key 生成器

typescript 复制代码
// 为 ForEach 提供 key 生成器,提高渲染效率
ForEach(
  this.healthReminders,
  (item: HealthReminder) => {
    ListItem() {
      // 列表项内容
    }
  },
  (item: HealthReminder) => item.title  // key 生成器
)

7.2 带 key 与不带 key 的对比

对比维度 不带 key 带 key
渲染效率 重新渲染所有项 只更新变化的项
动画过渡 不支持 支持 item 动画
数据变化 全部重建 精准更新
推荐度 小列表可用 推荐使用

八、列表项样式统一

8.1 列表项容器

typescript 复制代码
// 列表项的统一样式
Row({ space: 12 }) {
  // 内容...
}
.width('100%')
.padding(12)                     // 内边距 12vp
.backgroundColor('#FFFFFF')      // 白色背景
.borderRadius(12)                // 12vp 圆角

8.2 列表项间距

typescript 复制代码
// 列表项之间的间距由外层 Column 的 space 控制
Column({ space: 12 }) {
  // 标题行
  // 列表项 1
  // 列表项 2(如果有)
}

九、空状态与加载状态

9.1 空状态

typescript 复制代码
// 当没有提醒时显示空状态
if (this.healthReminders.length === 0) {
  Column() {
    Text('🎉')
      .fontSize(48)
    Text('暂无健康提醒')
      .fontSize(14)
      .fontColor('#999999')
      .margin({ top: 8 })
    Text('点击 + 添加提醒')
      .fontSize(12)
      .fontColor('#F5A623')
      .margin({ top: 4 })
  }
  .width('100%')
  .padding(24)
  .alignItems(HorizontalAlign.Center)
}

9.2 加载状态

typescript 复制代码
@State isLoading: boolean = true

aboutToAppear(): void {
  // 模拟加载数据
  setTimeout(() => {
    this.isLoading = false
  }, 1000)
}

// 加载中显示 Loading
if (this.isLoading) {
  LoadingProgress()
    .width(32).height(32)
    .color('#F5A623')
}

十、最佳实践

10.1 列表设计原则

有序列表 --- 列表设计的 5 个原则:

  1. 数据驱动:使用 ForEach 动态渲染,数据变化 UI 自动更新
  2. 信息层级:图标 > 标题 > 日期 > 辅助信息,从左到右重要性递减
  3. 交互反馈:可点击的列表项提供点击反馈
  4. 状态指示:倒计时使用颜色区分紧急程度
  5. 空状态友好:列表为空时展示引导文案

10.2 萌宠日记健康提醒列表总结

设计要素 说明
布局 Row + Column 嵌套 水平布局 + 垂直布局
图标容器 44×44vp 圆角 12vp
标题字号 14fp 中等强调
日期字号 12fp 辅助信息
倒计时色 #F5A623 橙色引人注意
背景色 #FFFFFF 白色
圆角 12vp 柔和

总结

本文从 萌宠日记健康提醒列表 实现出发,深入解析了列表动态渲染和数据绑定的完整方法:

  1. 数据模型:HealthReminder 接口定义提醒数据结构
  2. 列表渲染:ForEach 动态渲染提醒列表
  3. 列表项布局:图标 + 标题 + 日期 + 倒计时 + 右箭头
  4. 标题行设计:标题 + 添加按钮
  5. 动态数据绑定:@State 驱动 UI 自动更新
  6. 倒计时计算:日期计算与颜色状态指示
  7. 交互反馈:点击跳转、添加按钮
  8. 空状态处理:无提醒时的引导展示

健康提醒列表展示了 ArkTS 中数据驱动 UI 的典型模式,理解这一模式能为构建更复杂的列表页面打下基础。

下一篇我们将深入 图标与 Emoji 在 UI 中的应用,解析 Emoji 作为 UI 图标的优势和选择策略。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

相关推荐
HONG````1 小时前
HarmonyOS 6.1 实战:Stack 层叠布局与 Overlay 浮层详解
后端
程序员cxuan2 小时前
离谱,GPT-5.6 竟然在后台执行了 rm -rf
人工智能·后端·程序员
Csvn2 小时前
📊 SQL 入门 Day 9:CTE(公用表表达式)— 让 SQL 像写代码一样优雅
后端·sql
运维行者_2 小时前
如何查看每个IP的带宽使用情况?NetFlow 技术实战指南
开发语言·网络·分布式·后端·架构·带宽
济*沧*海3 小时前
如何判断接口的返回值?
后端
杨充3 小时前
5.多用组合和少继承
后端
杨充3 小时前
4.接口而非实现编程
java·后端·架构
一缕清烟在人间3 小时前
HarmonyOS应用开发实战:萌宠日记 - 生命周期在萌宠日记中的实践
后端
Conan在掘金3 小时前
鸿蒙 ArkUI 组件深水区:Span 富文本嵌套,一行 Text 塞下「红蓝斜下大」五样式 + 动态高亮
后端