# 鸿蒙 HarmonyOS 应用开发实战(第37期)|购物清单(Shopping List)— 勾选标记与线性进度条 📅 2026/7/30 3:08:06 一、应用概述购物清单Shopping List是一款实用的日常购物管理工具。用户可以添加待购商品通过点击复选框标记已购商品并实时查看购买进度已购/总数 和 进度条。应用支持单个删除和批量清除已购商品帮助用户高效管理购物流程。在 ArkTS 技术层面购物清单是列表操作集大成者——它完整实现了增添加商品、改勾选切换、删单删/批量清除三种操作并引入了Progress的Linear线性类型作为进度指示器。相比第 36 期的阅读清单购物清单增加了复选框交互和清除已购功能交互模式更加丰富。二、技术架构与组件树2.1 整体架构Entry Component struct index37 ├── Column (根容器) │ ├── Row (顶部导航栏) │ ├── Row (添加区) │ │ ├── TextInput (输入商品名, layoutWeight1) │ │ └── Button (添加) │ ├── Row (信息栏) │ │ ├── Text (已购 N/M) │ │ ├── Blank() │ │ └── if (checkedCount 0) → Text (清除已购) │ ├── Progress (Linear 线性进度条, width92%, height6) │ └── List (商品列表, layoutWeight1) │ └── ForEach → ListItem → Row │ ├── Text (☑️/⬜ 复选框) │ ├── Text (商品名, 可删除线) │ └── Text (✕ 删除)2.2 数据模型interface ShopItem { id: number; name: string; checked: boolean; } State items: ShopItem[] []; State inputText: string ; nextId: number 1;ShopItem接口定义了商品的三个属性唯一 ID、名称、是否已购。与阅读清单的 Book 接口相比这里的status被简化为一个checked布尔值——因为购物清单只有「已购/未购」两种状态不需要三态流转。三、核心代码深度解析3.1 添加商品——输入校验与不可变追加addItem(): void { const t this.inputText.trim(); if (t ) return; const newItems: ShopItem[] this.items.concat(); newItems.push({ id: this.nextId, name: t, checked: false }); this.items newItems; this.inputText ; }关键细节this.inputText.trim()去除首尾空格后判断是否为空——防止用户只输入空格concat()创建副本 →push()添加 → 重新赋值标准的不可变更新三步曲新商品默认checked: false未购添加后清空输入框3.2 勾选切换——布尔值的翻转toggleItem(id: number): void { const newItems: ShopItem[] this.items.concat(); for (let i 0; i newItems.length; i) { if (newItems[i].id id) { newItems[i] { id: newItems[i].id, name: newItems[i].name, checked: !newItems[i].checked }; } } this.items newItems; }核心操作是!newItems[i].checked——布尔值的取反操作。与阅读清单的三态切换不同这里只需要在 true/false 之间翻转。同样使用不可变更新模式创建副本 → 修改副本 → 重新赋值。3.3 删除与批量清除deleteItem(id: number): void { const newItems: ShopItem[] []; for (let i 0; i this.items.length; i) { if (this.items[i].id ! id) { newItems.push(this.items[i]); } } this.items newItems; } clearChecked(): void { const newItems: ShopItem[] []; for (let i 0; i this.items.length; i) { if (!this.items[i].checked) { newItems.push(this.items[i]); } } this.items newItems; }两种删除模式deleteItem按 ID 精确删除单个商品匹配 ID 则排除clearChecked批量删除所有已购商品已购则排除两种方法都使用了相同的不可变过滤模式。clearChecked特别有用——当用户一次购买多件商品后可以一键清空已购项让清单恢复到「只显示未购商品」的状态。3.4 计算属性已购统计与进度get checkedCount(): number { let count 0; for (let i 0; i this.items.length; i) { if (this.items[i].checked) count; } return count; } get progress(): number { if (this.items.length 0) return 0; return (this.checkedCount / this.items.length) * 100; }checkedCount统计已购数量progress计算购买进度百分比。注意progress的边界处理当列表为空时直接返回 0避免除以零的错误。3.5 复选框与删除线Text(item.checked ? ☑️ : ⬜).fontSize(22) .onClick(() this.toggleItem(item.id)) Text(item.name) .fontSize(16) .decoration({ type: item.checked ? TextDecorationType.LineThrough : TextDecorationType.None }) .fontColor(item.checked ? #aaa : #333)两个视觉反馈同步变化复选框图标未购显示空框⬜已购显示勾选框☑️文字样式未购为深色 (#333) 无修饰已购为灰色 (#aaa) 删除线TextDecorationType.LineThrough是 ArkTS 的文本装饰属性支持三种类型None无装饰LineThrough删除线中划线Underline下划线Overline上划线删除线是一种强烈的视觉信号——即使只看一眼也能立即分辨哪些商品已经购买。3.6 线性进度条Row() { Text(已购 this.checkedCount / this.items.length) .fontSize(13).fontColor(#888) Blank() if (this.checkedCount 0) { Text(清除已购).fontSize(13).fontColor(#F44336) .onClick(() this.clearChecked()) } }.width(92%).margin({ bottom: 4 }) Progress({ value: this.progress, total: 100, type: ProgressType.Linear }) .width(92%).height(6).borderRadius(3).color(#4CAF50)ProgressType.Linear是水平进度条与第 34 期的环形进度条相比特性Linear线性Ring环形视觉风格紧凑、简洁醒目、适合中心内容空间占用一行高度正方形区域适用场景列表中的进度指示数据看板、仪表盘本例用途购物清单底部进度计步器环形步数Blank()组件充当弹性空白将「已购 N/M」和「清除已购」推到行的两端——这是一种简化版的justifyContent: SpaceBetween实现。清除已购使用条件渲染只有当存在已购商品时才显示。这避免了用户看到一个无效按钮的困惑。四、HarmonyOS 特性分析4.1 TextDecorationType 文本装饰.decoration({ type: TextDecorationType.LineThrough, color?: Color })decoration属性不仅可以设置装饰类型还可以指定装饰线的颜色可选。在购物清单中商品名称的颜色和装饰线同步变化未购#333 无装饰已购#aaa 删除线这种「颜色淡化 删除线」的组合比单独使用删除线更易读。4.2 Blank 弹性空白组件Blank()是 ArkTS 中的一个特殊组件它会占据所有可用的剩余空间相当于flex: 1的空盒子。在 Row 中Blank()可以将前后的组件推到两端实现类似justifyContent: SpaceBetween的布局效果。4.3 onSubmit 事件优化输入体验TextInput({ placeholder: 添加商品..., text: this.inputText }) .onChange((v: string) { this.inputText v }) .onSubmit(() this.addItem())onSubmit事件在用户点击键盘的「确认」或「→」键时触发。这允许用户在输入商品名后直接按键盘确认添加无需手动点击「添加」按钮大幅提升操作效率。五、UI/UX 设计与最佳实践5.1 清单交互的最佳实践自然映射复选框⬜/☑️的交互与真实购物场景一致——在纸上打勾删除线反馈已购商品的删除线提供了强烈的完成感进度可视化进度条 数字统计双重复合反馈批量操作「清除已购」一键清理避免逐项删除的繁琐5.2 信息层级设计页面从上到下的信息流输入区操作入口添加商品统计区当前状态概览已购/总数 进度条列表区详细清单可操作的具体商品这种「概览 → 详情」的布局让用户先了解整体进度再聚焦到具体商品。5.3 错误预防空输入保护trim()后检查禁止添加纯空格的商品名空列表保护progress计算时对空列表的特殊处理条件显示「清除已购」只在需要时显示六、可扩展思路商品分类支持为商品添加分类标签蔬果、肉类、日用品按分类分组显示。数量/单位支持设置商品数量如 2 瓶牛奶和单位瓶、斤、个。购物模式进入购物模式后点击商品直接标记已购并打勾同时伴随振动反馈。多清单管理支持创建多个购物清单如「周末采购」「旅行用品」。数据持久化与导出保存清单到本地支持导出为文本文件。七、总结购物清单应用以 118 行代码实现了一个功能完善的购物管理工具。它的技术亮点包括增删改查完整 CRUD添加、勾选、单删、批量清除四项操作全覆盖Progress Linear 进度条线性进度指示器的标准用法TextDecoration 文本装饰删除线在清单类应用中的经典应用条件渲染清除按钮的按需显示Blank 弹性布局实现信息栏两端对齐onSubmit 快捷操作键盘确认添加提升输入效率这个应用的架构模式——列表数据 复选框交互 进度条统计——是任务管理、待办事项、检查清单等各类清单应用的通用模板。下一期我们将从清单工具转向安全领域探讨一个趣味十足的应用——密码锁Password Lock看如何用 Grid 网格布局构建数字密码键盘。本文是 HarmonyOS 应用开发实战系列第 37 期更多内容请关注专栏。