鸿蒙 ArkTS 实战:Pet Meetup 从宠物聚会到兴趣活动工具完整解析

前言

Pet Meetup 是一个围绕 社区活动 场景设计的鸿蒙 ArkTS 单页应用。

它的价值不在于复杂功能堆叠,而在于把 维护宠物资料、活动名称、疫苗状态、照片数量和报名反馈 这件事压缩成一个可以快速打开、快速记录、快速反馈的移动端页面。

本文会基于项目真实的 Index.ets 代码,拆解它的状态模型、布局结构、交互逻辑、视觉层级和可扩展方向。

在这里插入图片描述

图示说明:配图用于表达鸿蒙 ArkTS 应用从状态、组件到交互反馈的组织方式,重点帮助理解页面结构。

阅读时可以结合 HarmonyOS 应用开发文档ArkTS 语言基础ArkUI 声明式开发范式组件参考 等资料,快速定位 ArkTS、ArkUI 与组件开发相关能力。

小型兴趣活动工具最重要的是把一次操作闭环做完整:用户输入什么、点击什么、页面反馈什么,都要一眼能看懂。

一、应用定位与场景价值

1.1 解决的真实问题

宠物聚会 解决的是一个非常具体的场景:维护宠物资料、活动名称、疫苗状态、照片数量和报名反馈。

这类应用通常不需要复杂的账号系统,也不需要一开始就接入云端。

它首先要做到的是让用户在一个页面里完成核心记录。

1.2 适合的用户群体

本文面向 想实现社区活动报名、资料卡和状态提示的鸿蒙开发者。

从代码学习角度看,这个项目适合观察三件事。

  1. 如何用 @State 保存页面数据。
  2. 如何用 ArkUI 组件表达业务结构。
  3. 如何让按钮事件形成即时反馈。

1.3 为什么用鸿蒙 ArkTS 实现

ArkTS 的声明式 UI 写法适合这类工具。

状态在组件中声明,组件直接引用状态,事件函数修改状态,界面随之更新。

这种写法能把业务逻辑和页面反馈放在一起阅读,对学习项目尤其友好。

二、工程入口与页面骨架

2.1 页面文件位置

项目核心页面位于 Index.ets

entry/
  src/
    main/
      ets/
        pages/
          Index.ets

入口页面承担了三个职责:声明状态、处理交互、构建 UI。

2.2 入口组件声明

项目使用 @Entry@Component 声明页面组件。

@Entry
@Component
struct Index {
  build() {
    // 页面结构
  }
}

这种结构是鸿蒙 ArkUI 页面开发的基础模式。

2.3 页面骨架特征

Pet Meetup 的页面骨架可以概括为:顶部资料卡展示宠物信息,中间 Row 显示疫苗状态和照片数,底部按钮处理报名和照片分享。

这个骨架很适合移动端,因为主信息直接进入首屏,辅助信息通过输入区和结果区逐步展开。

三、状态模型拆解

3.1 状态字段总览

状态字段 初始值 页面职责
pet Momo, corgi, 3y 宠物资料
eventName Sunday park walk 活动名称
vaccine true 疫苗状态
photos 12 照片数量
signup 4 pets joined 报名状态

这些状态字段覆盖了 宠物聚会 的主要业务信息。

3.2 状态字段的语义边界

状态字段不是随意命名的变量,而是页面语义的一部分。

例如 pet 表达主记录,signup 表达反馈状态。

这种命名方式让读者不需要跳转多个文件,也能理解页面正在做什么。

3.3 核心源码片段

@State pet: string = 'Momo, corgi, 3y';
@State eventName: string = 'Sunday park walk';
@State vaccine: boolean = true;
@State photos: number = 12;
@State signup: string = '4 pets joined';

这段代码展示了页面数据如何被声明和更新。

对于小型工具来说,把状态集中放在入口组件中是可读性很高的做法。

四、交互逻辑设计

4.1 交互点总览

交互点 源码行为 页面反馈
Sign Up 把活动名称写入报名反馈 用户能立即看到状态变化
Share Photo 照片数量加一 用户能立即看到状态变化
vaccine 条件色 根据 true 或 false 展示通过或待检查状态 用户能立即看到状态变化

交互点的共同特点是动作短、反馈快。

用户点击按钮后,页面不会跳转到复杂流程,而是直接更新当前页面可见的文字或数字。

4.2 输入框的同步机制

输入框通过 onChange 把用户输入写回状态。

TextInput({ text: this.pet, placeholder: '宠物资料' })
  .onChange((v: string) => this.pet = v)

这种方式适合字段数量有限的页面。

当字段变多时,可以抽出通用输入组件,减少重复代码。

4.3 结果反馈的表达方式

结果反馈应该能复述用户刚刚完成的动作。

this.signup = 'Updated by ' + this.pet;

清晰反馈能让用户确认操作已经生效。

五、布局结构与视觉层级

5.1 关键 UI 片段

Row({ space: 10 }) {
  Text(this.vaccine ? 'Vaccine OK' : 'Need Check').layoutWeight(1)
    .padding(16).backgroundColor(this.vaccine ? '#DCFCE7' : '#FEE2E2')
  Text('Photos\n' + this.photos).layoutWeight(1).padding(16).backgroundColor('#DBEAFE')
}

这段代码是项目最有代表性的布局部分。

它通过 RowColumnGridScroll 或条件背景色,把关键状态放到更容易被注意的位置。

5.2 页面主次关系

页面主次关系可以分为三层。

  • 第一层:标题、比分、人数、地点或主卡片。
  • 第二层:输入字段和操作按钮。
  • 第三层:状态说明、提醒和补充记录。

这种分层让用户可以先看结果,再决定是否编辑细节。

5.3 滚动区域的必要性

很多活动工具都包含多个字段。

使用 Scroll 可以保证小屏设备也能完整操作。

Scroll() {
  Column({ space: 16 }) {
    // 内容区
  }
  .padding(20)
  .width('100%')
}

滚动容器让页面保持稳定,也避免按钮被屏幕高度挤出。

六、数据计算与边界处理

6.1 字符串状态处理

多数活动工具会把多个输入字段组合成一段反馈。

const summary = this.pet + ' / ' + this.signup;

这种拼接不是简单展示,而是把零散输入变成可阅读的活动记录。

6.2 数字状态处理

项目中涉及人数、比分、照片、费用、点数或签到数等数字。

this.count++;
const split = Math.round(Number(this.cost) / this.members);

数字状态要特别关注两个点:类型转换和边界值。

6.3 条件展示处理

当页面需要根据状态改变样式时,可以使用条件表达式。

Text(this.enabled ? 'Ready' : 'Pending')
  .backgroundColor(this.enabled ? '#DCFCE7' : '#FEE2E2')

条件样式能让用户在不读长文本的情况下理解状态。

七、活动工具的体验设计

7.1 首屏信息要明确

Pet Meetup 的首屏把关键状态放在最显眼的位置。

对于 社区活动 场景,用户通常是在活动现场或活动前快速查看信息。

因此页面不应该隐藏最重要的内容。

7.2 输入成本要低

项目采用短输入框和短按钮文案,降低了记录成本。

输入类型 页面用途 体验特点
文本输入 记录名称、地点、说明 灵活
数字输入 记录费用、人数、比分 直观
按钮点击 加入、签到、投票、提交 快速

7.3 反馈要贴近场景

不同场景的反馈文案不应该完全一样。

宠物聚会 的反馈围绕 维护宠物资料、活动名称、疫苗状态、照片数量和报名反馈 展开,因此用户读到结果时能知道它对应哪一次活动。

八、组件能力映射

8.1 ArkUI 组件使用

组件 在项目中的作用 适合原因
Text 显示标题、状态和结果 简洁直接
TextInput 编辑活动信息 输入成本低
Button 触发状态变化 操作明确
Row 横向展示多个指标 适合并列信息
Column 纵向组织内容 阅读顺序自然

8.2 布局参数的作用

页面中常见的 .padding(20).borderRadius(8).layoutWeight(1) 都是为了保证移动端可读性。

Text('Card')
  .padding(16)
  .backgroundColor('#FEF3C7')
  .borderRadius(8)

这些参数让卡片有足够留白,也让并列内容更加稳定。

8.3 背景色与强调色

当前页面背景色是 #FFFFFF,强调色是 #FEF3C7

背景色负责降低阅读压力,强调色负责突出当前最重要的信息。

九、可维护性分析

9.1 当前实现的优点

Pet Meetup 当前实现有几个优点。

  • 状态字段数量适中。
  • 交互函数短小。
  • 页面结构集中。
  • 业务语义明确。
  • 适合继续迭代。

这些特点让项目很适合作为鸿蒙 ArkTS 实战文章案例。

9.2 可能增长的复杂度

当活动记录变多后,复杂度会从单条状态转向列表数据。

例如报名名单、历史比分、材料采购明细、照片集合和路线记录,都可能需要数组结构。

9.3 数据对象示例

interface ActivityRecord {
  id: string;
  title: string;
  detail: string;
  count: number;
  updatedAt: number;
}

把记录抽象成对象后,页面就可以从单次工具升级为历史记录工具。

十、列表化扩展

10.1 数组状态

@State records: ActivityRecord[] = [];

数组状态适合保存多条活动记录。

10.2 渲染列表

ForEach(this.records, (item: ActivityRecord) => {
  Text(item.title)
    .fontSize(18)
    .fontWeight(FontWeight.Medium)
})

列表化之后,用户可以回看历史活动,而不是只看当前一次记录。

10.3 新增记录

this.records = [
  ...this.records,
  {
    id: Date.now().toString(),
    title: this.pet,
    detail: this.signup,
    count: 1,
    updatedAt: Date.now()
  }
];

这种不可变更新方式更容易触发页面刷新。

十一、本地持久化思路

11.1 为什么需要持久化

活动类工具一旦进入真实使用,就需要保存历史数据。

如果不持久化,用户每次重新打开页面都会失去上一次记录。

11.2 持久化数据结构

interface PersistedActivityState {
  currentTitle: string;
  currentDetail: string;
  records: ActivityRecord[];
  version: number;
}

加入 version 可以为后续字段升级预留空间。

11.3 读取后的状态恢复

function restoreTitle(saved: PersistedActivityState): string {
  return saved.currentTitle || '';
}

恢复状态时要考虑旧数据缺字段的情况。

十二、调试路径

12.1 先看状态是否变化

Button('Debug')
  .onClick(() => {
    console.info('current value: ' + this.pet);
  })

如果日志变化而页面不变,通常是 UI 没有引用正确字段。

12.2 再看数字计算

涉及费用、人均、比分和人数时,要检查输入为空或无法转换数字的情况。

const raw = Number(this.cost);
const safeCost = Number.isNaN(raw) ? 0 : raw;

这能避免用户输入异常时出现不可读结果。

12.3 最后看小屏适配

小屏设备上要重点观察输入框、按钮和卡片是否拥挤。

如果内容多,优先保证 Scroll 可用。

十三、常见问题处理

13.1 输入为空

输入为空时,可以继续显示 placeholder,并在结果区保留最近一次有效反馈。

13.2 数字不合法

数字输入要考虑空字符串。

function toSafeNumber(value: string): number {
  const n = Number(value);
  return Number.isNaN(n) ? 0 : n;
}

这样能避免费用分摊或统计显示出现异常。

13.3 文本过长

文本过长时,可以用滚动容器承接,而不是让卡片无限撑高。

维度 当前实现 扩展方向
数据来源 页面内 @State 可接入本地持久化
交互方式 输入框加按钮 可加入筛选、搜索和批量操作
视觉重点 #FEF3C7 强调主信息 可形成主题色配置
使用场景 维护宠物资料、活动名称、疫苗状态、照片数量和报名反馈 可扩展成多记录管理

十四、工程化拆分

14.1 抽离卡片组件

@Builder
function MetricCard(label: string, value: string, color: string) {
  Column({ space: 6 }) {
    Text(label).fontSize(14).fontColor('#6B7280')
    Text(value).fontSize(20).fontWeight(FontWeight.Bold)
  }
  .padding(16)
  .backgroundColor(color)
  .borderRadius(8)
}

这个组件可以复用在人数、比分、费用、签到和照片等指标上。

14.2 抽离业务函数

export function buildActivityStatus(title: string, action: string): string {
  return title + ' - ' + action;
}

业务函数独立后,页面代码会更专注于 UI。

14.3 抽离主题配置

const Theme = {
  pageBg: '#FFFFFF',
  accent: '#FEF3C7',
  radius: 8,
  padding: 20
};

统一主题配置可以减少重复修改。

十五、发布级技术亮点

15.1 单页闭环完整

宠物聚会 已经完成从输入到反馈的闭环。

用户可以在一个页面里完成主要操作,而不需要跳转。

15.2 业务语义清楚

字段名、按钮名和结果文本都围绕 社区活动 展开。

这让代码不仅能运行,也能被读懂。

15.3 易于继续扩展

当前实现可以自然扩展到历史记录、数据持久化、统计图和分享能力。

对活动类应用来说,先把一次活动记录做顺,再扩展到多次活动管理,是更稳的产品演进路线。

十六、总结

Pet Meetup 展示了一个鸿蒙 ArkTS 小应用如何把 社区活动 场景落到页面代码里。

它用 @State 保存核心数据,用输入框完成编辑,用按钮触发状态变化,再通过卡片、数字和结果文本反馈给用户。

从学习价值看,这个项目覆盖了状态管理、布局组织、输入同步、按钮事件和视觉层级,是一个适合拆解和复用的单页工具案例。

从产品价值看,宠物聚会 把 维护宠物资料、活动名称、疫苗状态、照片数量和报名反馈 这件事变得更轻、更快、更容易执行。


相关资源:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐