鸿蒙 ArkTS 实战:Appliance Maintenance 从状态建模到交互闭环完整解析

前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Appliance Maintenance 是一个面向 轻量工具应用 的鸿蒙 ArkTS 小应用。用设备档案、房间、保养状态和耗材提醒管理家电维护节奏。 本文围绕项目中的 entry/src/main/ets/pages/Index.ets 展开,拆解它的 数据模型@State 状态业务方法Builder 组件 和页面布局方式,帮助读者理解一个轻量鸿蒙应用如何从静态数据走向可交互页面。

在这里插入图片描述

图示说明:页面以卡片、列表、输入框、按钮和状态统计为主体,适合在 DevEco Studio 中作为 ArkTS 组件化练习项目。

一、项目定位与功能闭环

1.1 应用要解决的问题

Appliance Maintenance 的业务入口非常轻:用户打开页面后,先看到已有数据和统计信息,再通过输入框或按钮触发状态变化。它不是重后台项目,而是典型的 单页状态驱动应用

维度 项目表现 技术落点
数据承载 使用接口描述业务对象 interface
页面状态 使用 @State 保存列表、输入和开关 ArkTS 状态管理
交互动作 点击按钮后重建数组或修改字段 不直接突变旧数组
视觉组织 卡片、行组件、统计块 Builder 复用
运行环境 DevEco Studio + 鸿蒙 ArkTS Stage 模型页面

1.2 本文阅读重点

  1. 先看数据模型,理解页面到底在管理什么。
  2. 再看状态变量,判断哪些字段会触发 UI 刷新。
  3. 接着看核心方法,梳理新增、切换、筛选、统计等动作。
  4. 最后看页面布局,把业务数据映射成用户能理解的界面。

核心观点:ArkTS 页面开发的关键不是把控件堆满,而是让数据结构、状态变化和 UI 呈现形成稳定闭环。

二、工程结构与入口文件

2.1 目录结构

本项目是标准鸿蒙工程,核心页面位于 entry/src/main/ets/pages/Index.ets。文章聚焦这个文件,因为它包含了主要模型、状态、方法和 UI。

Appliance Maintenance
├── AppScope
├── entry
│   └── src
│       └── main
│           ├── ets
│           │   └── pages
│           │       └── Index.ets
│           └── module.json5
├── hvigor
├── build-profile.json5
└── oh-package.json5

2.2 页面入口

ArkTS 页面通过 @Entry 和 @Component 标记入口组件,uild() 方法负责描述 UI 树。

@Entry
@Component
struct Index {
  build() {
    Scroll() {
      Column() {
        // 页面内容
      }
    }
  }
}

2.3 技术栈表

技术点 用途 在项目中的角色
ArkTS 页面逻辑与类型声明 主开发语言
ArkUI 声明式组件 构建界面
@State 响应式状态 驱动刷新
@Builder 组件片段复用 降低重复布局
Hvigor 构建系统 工程构建

三、数据模型设计

3.1 模型清单

源码中出现的业务模型为:$ifaceList。这些接口用于约束列表数据结构,让 UI 渲染时能明确字段来源。

interface DeviceItem {
  id: number;
  title?: string;
  name?: string;
  done?: boolean;
  status?: string;
}

上面的代码展示了这类模型的常见形态:id 用于列表 key,名称字段用于展示,状态字段用于判断颜色、按钮文案和操作结果。

3.2 模型设计表

模型 主要价值 页面用途
$primaryInterface 承载核心业务条目 列表渲染、按钮操作
辅助模型 承载记录、提示或分类 详情展示、过滤统计
状态字段 表示完成、提醒、选中等状态 控制颜色和文案

3.3 为什么用 interface

ArkTS 中使用 interface 可以在编写对象数组时获得更强的结构约束,减少字段拼写错误。对于列表型应用,这一点尤其重要。

实践要点:如果页面中有多条同结构数据,应优先抽象成接口,再让 @State 数组保存该接口类型。

四、状态变量拆解

4.1 @State 清单

项目中的状态声明包括:$stateList。

@State items: DeviceItem[] = [];
@State draftText: string = '';
@State selectedIndex: number = 0;
@State enabled: boolean = true;

实际源码会根据业务命名,例如列表、输入框、筛选条件、开关状态等。它们共同决定页面当前显示什么、按钮点击后更新什么。

4.2 状态分类

状态类型 示例 作用
列表状态 $primaryState 页面主体数据
输入状态 draftName、keyword、nswer 接收用户输入
选择状态 selectedId、 ilter、cursor 决定当前视图
开关状态
eminder、shared、
ecording 控制功能启停
统计状态 correct、wrong、seconds 形成即时反馈

4.3 状态更新原则

ArkTS 页面中,列表更新常采用重建数组的方式,这样更容易触发界面刷新。

private updateItem(id: number): void {
  this.items = this.items.map((item: DeviceItem) => {
    if (item.id !== id) {
      return item;
    }
    return {
      ...item,
      done: !item.done
    };
  });
}

五、核心方法解析

5.1 方法清单

源码中的核心方法包括:$methodList。这些方法构成了应用的业务动作层。

方法类型 常见方法 说明
统计方法 otal、count、verage 从列表中派生数字
新增方法 ddItem、ddTask 从输入状态创建新对象
切换方法 oggle、 inish、
ext 修改完成、提醒、进度
过滤方法 isible、 iltered 根据关键词或分类筛选
展示方法
ow、card、sectionHeader 组织 UI 片段

5.2 统计方法

很多轻量应用都需要顶部统计卡片。统计方法通常通过 ilter、
educe 或数组长度计算。

private countActive(): number {
  return this.items.filter((item: DeviceItem) => !item.done).length;
}

private totalValue(): number {
  return this.items.reduce((sum: number, item: DeviceItem) => sum + 1, 0);
}

5.3 新增方法

新增逻辑的关键是从输入框状态读取文本,做空值判断,再把新对象插入列表。

private addItem(): void {
  const title = this.draftText.trim();
  if (title.length === 0) {
    return;
  }
  const id = this.items.reduce((maxId: number, item: DeviceItem) => Math.max(maxId, item.id), 0) + 1;
  const item: DeviceItem = { id: id, title: title, done: false };
  this.items = [item, ...this.items];
  this.draftText = '';
}

5.4 切换方法

完成、提醒、收藏、订阅这类动作都可以通过 map 生成新数组。

private toggleItem(id: number): void {
  this.items = this.items.map((item: DeviceItem) => {
    return item.id === id ? { ...item, done: !item.done } : item;
  });
}

六、Builder 组件复用

6.1 Builder 清单

项目中的 Builder 组件包括:$builderList。

@Builder 适合承载重复出现的 UI 片段,比如统计卡、列表行、筛选按钮、章节标题等。

@Builder
private row(item: DeviceItem) {
  Row() {
    Text(item.title ?? item.name ?? '未命名')
      .fontSize(16)
      .fontWeight(FontWeight.Medium)
  }
  .padding(12)
  .backgroundColor('#FFFFFF')
  .borderRadius(8)
}

6.2 复用价值

Builder 复用价值 适用位置
统计卡片 避免重复写数字和标签布局 顶部概览
列表行 统一条目样式 主列表
筛选按钮 保持选中态一致 分类切换
区块标题 统一标题和辅助信息 页面分组

6.3 组件边界

Builder 不需要承担复杂业务判断,它更适合做“给定数据,渲染界面”。业务变化仍然放在 private 方法中。

七、页面布局结构

7.1 Scroll + Column

这批项目大多采用 Scroll 包裹 Column 的布局方式,适合移动端纵向内容流。

Scroll() {
  Column() {
    // 头部区域
    // 输入区域
    // 列表区域
    // 详情区域
  }
  .width('100%')
  .padding(16)
}
.height('100%')
.width('100%')

7.2 页面分区

分区 作用 常用组件
头部 展示标题、说明、统计 Text、Row、Column
输入区 接收新增数据 TextInput、Button
操作区 筛选、切换、开关 Button、Toggle
列表区 展示业务条目 ForEach、Builder 行
结果区 展示统计或详情 Card 风格容器

7.3 ForEach 渲染

列表通常通过 ForEach 渲染,并使用 id 作为稳定 key。

ForEach(this.items, (item: DeviceItem) => {
  this.row(item)
}, (item: DeviceItem) => item.id.toString())

稳定 key 能减少列表刷新时的错位,也更利于后续扩展动画或局部更新。

八、交互闭环设计

8.1 从输入到列表

新增动作通常经过以下路径:

  1. TextInput 的 onChange 更新草稿状态。
  2. Button 的 onClick 调用新增方法。
  3. 新增方法创建业务对象。
  4. 列表状态重建,页面自动刷新。
TextInput({ text: this.draftText })
  .onChange((value: string) => {
    this.draftText = value;
  })

Button('添加')
  .onClick(() => {
    this.addItem();
  })

8.2 从按钮到状态

切换类按钮不需要复杂表单,只要传入条目 id 即可。

Button('完成')
  .onClick(() => {
    this.toggleItem(item.id);
  })

8.3 状态反馈

按钮文案、颜色、标签和统计数字都来自状态。这样用户的每次点击都能马上看到反馈。

关键点:页面反馈越直接,工具应用越容易形成“点一下就知道结果”的操作感。

九、视觉层与信息层

9.1 色彩表达

项目常用白色卡片承载内容,用主题色突出主按钮,再用绿色、橙色、红色表达安全、待处理、异常等状态。

状态 色彩倾向 用户理解
正常 绿色 已完成、可用、安全
待处理 橙色 需要关注
异常 红色 需要立即处理
中性 灰色 普通说明

9.2 文本层级

标题使用较大字号,列表项名称使用中等字号,说明文本使用小字号。这样的层级适合小屏阅读。

Text('页面标题')
  .fontSize(30)
  .fontWeight(FontWeight.Bold)

Text('辅助说明')
  .fontSize(14)
  .fontColor('#667085')

十、鸿蒙 ArkTS 开发要点

10.1 类型先行

先定义接口,再写状态数组,可以让页面开发更稳。

10.2 状态集中

当前项目把状态集中在 Index 组件内,适合轻量单页应用。随着功能增加,可以再拆分组件或引入持久化。

10.3 方法命名

源码中的 $primaryMethod 等方法名直观表达动作,有利于阅读和维护。

10.4 UI 与逻辑分离

Builder 负责渲染,private 方法负责业务动作,这种分工能让页面不至于变成一整块难读代码。

十一、运行与调试流程

11.1 使用 DevEco Studio 打开

# 使用 DevEco Studio 打开项目目录
# 同步 oh-package 依赖
# 选择模拟器或真机运行 entry 模块

11.2 命令行构建思路

hvigorw clean
hvigorw assembleHap

11.3 调试观察点

观察点 关注内容
页面是否进入 @Entry 是否正常加载
列表是否刷新 @State 数组是否重建
输入是否生效 onChange 是否写回状态
按钮是否响应 onClick 是否调用方法
样式是否稳定 卡片宽度、颜色、字号是否一致

十二、可维护性拆解

12.1 文件规模

当前 Index.ets 约 116 行,属于可阅读的单页规模。随着功能继续增加,可以把列表行、统计卡和输入区拆到独立组件。

12.2 数据扩展

如果要接入本地存储,可以先为 $primaryInterface 增加序列化字段,再在页面加载时恢复列表。

interface StoredRecord {
  id: number;
  payload: string;
  updatedAt: number;
}

12.3 异常边界

输入为空时直接返回,是轻量应用常见处理方式。更复杂的产品可以加入 Toast 或错误提示。

十三、同类项目迁移思路

13.1 可复用结构

Appliance Maintenance 的结构可以迁移到很多轻量工具:

  • 一组业务对象。
  • 一组页面状态。
  • 若干统计方法。
  • 一个新增入口。
  • 一个列表展示区。

13.2 抽象模板

interface ItemModel {
  id: number;
  title: string;
  done: boolean;
}

@State items: ItemModel[] = [];

private addItem(title: string): void {
  this.items = [{ id: Date.now(), title: title, done: false }, ...this.items];
}

13.3 适配范围

应用类型 可复用部分
清单工具 列表、完成状态、统计
记录工具 输入、历史、筛选
学习工具 进度、得分、卡片
家庭工具 提醒、状态、分组

十四、项目亮点总结

14.1 业务表达清晰

Appliance Maintenance 没有把逻辑藏在复杂框架里,而是直接用接口、状态和方法表达业务。

14.2 页面反馈及时

每个操作都会落到 @State,列表、统计和按钮状态随之变化。

14.3 结构适合继续扩展

当前结构可以自然扩展持久化、搜索、排序、通知和多页面跳转。

十五、总结

Appliance Maintenance 展示了鸿蒙 ArkTS 单页应用的典型写法:通过 $ifaceList 建模业务数据,通过 $stateList 保存页面状态,通过 $methodList 完成统计、筛选、新增和切换,再通过 $builderList 把重复 UI 片段组件化。它的价值不只是一个具体工具,而是一套可以迁移到其他轻量应用的工程组织方式。

对于正在学习鸿蒙 ArkTS 的开发者来说,这个项目适合重点观察三件事:数据模型如何约束页面、状态变化如何驱动 UI、Builder 如何让列表和卡片保持一致。掌握这三点后,就能快速搭建更多家庭、学习、办公类小工具。

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


相关资源:

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐