文章目录
- [鸿蒙 ArkTS 入门教程:小白实战 List 列表开发(详解 @State, ForEach, @Builder)](#鸿蒙 ArkTS 入门教程:小白实战 List 列表开发(详解 @State, ForEach, @Builder))
-
- [STEP 1: "兵马未动,粮草先行"------定义数据模型](#STEP 1: “兵马未动,粮草先行”——定义数据模型)
- [STEP 2: 开张!创建页面和"魔法"状态](#STEP 2: 开张!创建页面和“魔法”状态)
- [STEP 3: 搭建"货架"------布局和标题](#STEP 3: 搭建“货架”——布局和标题)
- [STEP 4: 循环"上货"------ List 和 ForEach 闪亮登场](#STEP 4: 循环“上货”—— List 和 ForEach 闪亮登场)
- [STEP 5: "私人订制"------ @Builder 自定义卡片组件](#STEP 5: “私人订制”—— @Builder 自定义卡片组件)
-
- [5.1 卡片左侧:图标和分类](#5.1 卡片左侧:图标和分类)
- [5.2 卡片右侧:名称、价格和描述](#5.2 卡片右侧:名称、价格和描述)
- [5.3 收尾:卡片样式和点击事件](#5.3 收尾:卡片样式和点击事件)
- [🏁 总结:你的鸿蒙之旅已启程](#🏁 总结:你的鸿蒙之旅已启程)
鸿蒙 ArkTS 入门教程:小白实战 List 列表开发(详解 @State, ForEach, @Builder)
摘要: 本文是一篇鸿蒙 ArkTS 小白入门教程。通过一个"国风"商品列表 Demo,带你实战学习 ArkTS 的 List 列表、ForEach 循环、@State 状态管理和 @Builder 自定义组件。从零开始,快速掌握鸿蒙列表页面的开发核心。
Hello 大家好!刚开始学鸿蒙(HarmonyOS)开发,是不是感觉 ArkTS 有点东西?别怕,今天我(一个和你一样刚起步的萌新)就来分享一下我的学习 Demo 笔记------一个看起来"高大上"的中国传统文化商品展示页!

别看它长得复古,用的知识点可都是"潮牌":List 列表 、ForEach 循环 、@State 状态管理 和 @Builder 自定义组件。
别看名词多,其实捅破了就那层窗户纸!上车,出发!
STEP 1: "兵马未动,粮草先行"------定义数据模型

在写界面之前,我们得先告诉程序,咱们的"商品"长啥样。总不能空手套白狼吧?
咱们先用 class 定义一个 CultureProduct(文化产品)类。它就像一个商品说明书模板,规定了每个商品必须有 ID、名字、价格、表情包(bushi,是 emoji 图标)、描述和分类。这就是咱们的数据结构。
typescript
// 中国传统文化商品展示 Demo
// 知识点:List列表、ForEach循环、@State状态管理、自定义组件
// 商品数据模型
class CultureProduct {
id: number;
name: string;
price: number;
emoji: string;
description: string;
category: string;
constructor(id: number, name: string, price: number, emoji: string, description: string, category: string) {
this.id = id;
this.name = name;
this.price = price;
this.emoji = emoji;
this.description = description;
this.category = category;
}
}
STEP 2: 开张!创建页面和"魔法"状态

有了模板,咱们就该创建页面(@Component)了。@Entry 告诉系统:"嘿,这就是我的店门面,程序从这里启动!"
最关键的来了:@State 装饰器。这玩意儿是鸿蒙 ArkTS 的"响应式魔法"之一。
用 @State 标记的 productList(我们的商品列表)一旦发生变化(比如你以后做了个"添加商品"按钮),UI 界面就会自动刷新!再也不用手动操作 DOM 了,是不是很爽?
我们先"伪造"一点数据,把 productList 填满,开张大吉!
typescript
@Entry
@Component
export struct CultureProductDemo {
// 商品列表数据
@State productList: CultureProduct[] = [
new CultureProduct(1, '青花瓷茶具', 688, '🫖', '景德镇手工青花瓷,传承千年工艺', '茶具'),
new CultureProduct(2, '宣纸书法套装', 298, '📜', '安徽宣纸,配毛笔墨汁,初学者首选', '文房四宝'),
new CultureProduct(3, '紫砂壶', 1280, '🍵', '宜兴紫砂,纯手工制作,养壶佳品', '茶具'),
new CultureProduct(4, '中国结挂饰', 88, '🪢', '手工编织,寓意吉祥如意', '装饰品'),
new CultureProduct(5, '古琴', 3800, '🎵', '桐木古琴,音色悠扬,附赠教学视频', '乐器'),
new CultureProduct(6, '景泰蓝花瓶', 1580, '🏺', '北京景泰蓝,宫廷工艺,收藏佳品', '工艺品'),
new CultureProduct(7, '汉服套装', 568, '👘', '明制汉服,刺绣精美,含配饰', '服饰'),
new CultureProduct(8, '围棋套装', 428, '⚫', '云子围棋,实木棋盘,适合对弈', '棋类')
];
STEP 3: 搭建"货架"------布局和标题

数据有了,咱得搭个货架(页面布局)。
每个组件都有一个 build() 方法,这是它的"化妆间",负责画出它的样子。我们先放一个 Column(),意思是里面的东西都给我垂直排好队。
然后加个 Text() 标题,调调字号、加粗、颜色啥的,让它看起来像个"标题党",专业!
typescript
build() {
Column() {
// 页面标题
Text('传统文化精品')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor('#8B4513')
.margin({ top: 20, bottom: 16 })
STEP 4: 循环"上货"------ List 和 ForEach 闪亮登场

重点来了!我们怎么把 @State 里的那一堆商品数据(productList)一个个摆到"货架"上?
答案是 List + ForEach 这对黄金搭档!
List: 顾名思义,就是个列表容器,自带"滚动"技能。ForEach: 这就是个"循环打印机"。它会遍历productList里的每一项 (我们临时叫它product),然后为每一项执行一次ListItem()里的操作。
在 ListItem() 里面,我们没有直接写一堆 Row、Column,而是调用了一个自定义组件 :this.ProductCard(product)。
这就像在说:"嘿,ProductCard 小弟(我们待会儿就定义它),这个 product 数据给你,你帮我把它画成一个卡片的样子!"
(layoutWeight(1) 是个小技巧,意思是让列表占满 Column 里的剩余所有空间。)
typescript
// 商品列表
List({ space: 12 }) {
ForEach(this.productList, (product: CultureProduct) => {
ListItem() {
this.ProductCard(product)
}
}, (product: CultureProduct) => product.id.toString())
}
.width('100%')
.layoutWeight(1)
.backgroundColor('#FFF8DC')
}
.width('100%')
.height('100%')
.padding({ left: 16, right: 16 })
.backgroundColor('#FFFAF0')
}
STEP 5: "私人订制"------ @Builder 自定义卡片组件

终于到了我们的大功臣------ProductCard 卡片组件!
这里用到了 @Builder 装饰器。你可以把它理解为一个"UI 蓝图生成器"。它是一个方法,你给它一个 product 数据,它就还你一个画好的 UI 组件。
这样做的好处是代码复用 和结构清晰 !如果以后想改卡片样式,只需要改这一个地方,List 里的所有卡片都会跟着变。
卡片内部,我们用一个 Row()(水平布局)分成了左右两部分。
typescript
// 商品卡片组件
@Builder
ProductCard(product: CultureProduct) {
Row() {
5.1 卡片左侧:图标和分类

左边是一个 Column()(垂直布局),放"表情包" emoji 和一个带背景色的 category 分类标签。调调间距和背景,小小的细节,瞬间提升 B 格。
typescript
// 左侧:商品图标和分类
Column() {
Text(product.emoji)
.fontSize(40)
Text(product.category)
.fontSize(10)
.fontColor('#FFFFFF')
.backgroundColor('#D2691E')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.margin({ top: 4 })
}
.width(80)
.height(80)
.justifyContent(FlexAlign.Center)
.backgroundColor('#FFF5EE')
.borderRadius(8)
5.2 卡片右侧:名称、价格和描述

右边也是一个 Column()(垂直布局),用来放商品信息。
- 第一行 :我们又用了一个
Row()(水平布局),左边放商品名称name(layoutWeight(1)让它抢占所有剩余空间),右边放价格price。 - 第二行 :放商品描述
description。注意maxLines(2)和textOverflow({ overflow: TextOverflow.Ellipsis }),这是防止描述太长"溢出"的经典操作,多余的字会变成"..."。
typescript
// 右侧:商品信息
Column() {
// 商品名称和价格
Row() {
Text(product.name)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#8B4513')
.layoutWeight(1)
Text('¥' + product.price)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#DC143C')
}
.width('100%')
.margin({ bottom: 8 })
// 商品描述
Text(product.description)
.fontSize(14)
.fontColor('#A0522D')
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.layoutWeight(1)
.padding({ left: 12 })
.alignItems(HorizontalAlign.Start)
5.3 收尾:卡片样式和点击事件

最后,我们给最外层的 Row()(也就是整个卡片)加上圆角、背景色、阴影(shadow 让它有"浮"起来的立体感),还有最重要的 onClick 点击事件!
现在,你点击任何一个商品卡片,控制台(Console)都会打印出你点击了谁。这就是交互的起点!
typescript
}
.width('100%')
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 8, color: '#E0E0E0', offsetX: 0, offsetY: 2 })
.onClick(() => {
console.info(`点击了商品:${product.name}`)
})
}
}
🏁 总结:你的鸿蒙之旅已启程

恭喜你!你已经成功完成了这个"国风"商品列表。我们来快速回顾一下你解锁的技能点:
- 数据模型 (Class): 搭建了应用的基础数据骨架。
- @State: 掌握了让 UI 自动"活"起来的响应式魔法。
- List + ForEach: 学会了如何高效地批量渲染数据。
- @Builder: 获得了创建可复用、高颜值 UI 模块的技能。
这几个知识点是 ArkTS 开发中名副其实的"基石"。
不要小看这个 Demo,你已经掌握了构建复杂列表页面的核心逻辑。这只是一个开始,继续保持这份好奇心,多动手实践,从这个小小的起点出发,一步步去探索鸿蒙世界的更多可能。相信自己,你的开发之路会越走越宽广!