HarmonyOS ArkTS 的新手练手样例:用 List 和 ForEach 做一个待办列表

开头

很多应用都绕不开列表:消息列表、商品列表、设置项、文章列表、任务列表。ArkTS 里可以用ListListItem展示列表,用ForEach根据数组生成重复界面。

这一篇我们做一个待办列表:输入任务,点击添加,下面列表自动多一条。

本篇目标

  • 会用数组保存列表数据。
  • 会用ForEach渲染多条内容。
  • 会用ListListItem组织列表。
  • 会删除列表中的某一项。

示例代码

interfaceTodoItem{id:number;title:string;done:boolean;}@Entry@Componentstruct TodoPage{@StateinputText:string='';@Statetodos:TodoItem[]=[{id:1,title:'学习 Text 和 Button',done:true},{id:2,title:'练习 TextInput',done:false}];privatenextId:number=3;privateaddTodo(){consttitle=this.inputText.trim();if(title.length===0){return;}this.todos=[...this.todos,{id:this.nextId,title,done:false}];this.nextId+=1;this.inputText='';}privateremoveTodo(id:number){this.todos=this.todos.filter((item:TodoItem)=>item.id!==id);}build(){Column({space:16}){Text('我的待办').fontSize(28).fontWeight(FontWeight.Bold).width('100%')Row({space:8}){TextInput({placeholder:'输入一个新任务',text:this.inputText}).layoutWeight(1).height(44).onChange((value:string)=>{this.inputText=value;})Button('添加').height(44).onClick(()=>{this.addTodo();})}List({space:10}){ForEach(this.todos,(item:TodoItem)=>{ListItem(){Row({space:12}){Text(item.done?'已完成':'未完成').fontSize(12).fontColor(item.done?'#008A45':'#666666')Text(item.title).fontSize(16).layoutWeight(1).decoration({type:item.done?TextDecorationType.LineThrough:TextDecorationType.None})Button('删除').height(32).onClick(()=>{this.removeTodo(item.id);})}.width('100%').padding(12).borderRadius(8).backgroundColor('#F5F5F5')}},(item:TodoItem)=>item.id.toString())}.layoutWeight(1).width('100%')}.width('100%').height('100%').padding(20)}}

小白看懂代码

todos是待办数组。列表页面一般都离不开数组。

ForEach(this.todos, ...)表示根据todos数组生成多条列表项。

ListItem()是列表中的一行。每一行里又放了一个Row,左边是状态,中间是任务标题,右边是删除按钮。

添加任务时,没有直接push

this.todos=[...this.todos,{id:this.nextId,title,done:false}];

这样写更符合声明式 UI 的思路:生成一个新的数组,再赋值给状态。

删除任务时用filter

this.todos=this.todos.filter((item:TodoItem)=>item.id!==id);

意思是保留所有id不等于目标值的任务。

为什么 ForEach 需要 key

代码最后有一段:

(item:TodoItem)=>item.id.toString()

这就是列表项的唯一标识。列表新增、删除、刷新时,框架需要知道“哪一条是哪一条”。实际项目中不要用重复值当 key。

可以怎么改

可以给每条任务加一个完成按钮:

Button(item.done?'恢复':'完成').height(32).onClick(()=>{this.todos=this.todos.map((todo:TodoItem)=>{if(todo.id===item.id){return{id:todo.id,title:todo.title,done:!todo.done};}returntodo;});})

也可以把待办列表改成文章列表、课程列表、商品列表。只要是“数组数据变成多行界面”,都可以先从这个例子改。

本篇小结

列表的核心不是List本身,而是“数据数组 + ForEach 渲染 + 唯一 key”。新手先把新增、删除跑通,再去学复杂的列表刷新、分页、懒加载,会轻松很多。

附录:项目设置与构建问题记录

一、项目设置

本篇配套一个独立 ArkTS 示例 App,用于运行页面和截图:

建议用 DevEco Studio 打开项目后运行entry模块。项目定位是截图练习 Demo,不依赖后端服务,也不需要额外权限。

建议新建或检查工程时保持以下设置:

  • Project type:Application。
  • Template:Empty Ability。
  • Language:ArkTS。
  • Model:Stage。
  • Device:Phone,可按需要兼容 Tablet、2in1。
  • Runtime OS:HarmonyOS。

二、SDK 版本

本文主题面向 HarmonyOS ArkTS API 24+。本次示例工程根目录build-profile.json5使用如下配置:

{ "compatibleSdkVersion": "6.1.1(24)", "targetSdkVersion": "6.1.1(24)", "runtimeOS": "HarmonyOS" }

如果本机 DevEco Studio SDK Manager 中安装的版本不同,请按本机实际 API 24+ SDK 调整compatibleSdkVersiontargetSdkVersion

三、项目目录说明

核心目录如下:

HarmonyOS_ArkTS_API24_ControlsScreenshotApp/ ├── AppScope/ │ ├── app.json5 │ └── resources/ ├── entry/ │ ├── src/main/ets/entryability/EntryAbility.ets │ ├── src/main/ets/pages/ │ ├── src/main/resources/base/profile/main_pages.json │ ├── build-profile.json5 │ └── oh-package.json5 ├── build-profile.json5 ├── hvigorfile.ts └── oh-package.json5

页面文件都在:

entry/src/main/ets/pages/

路由注册文件在:

entry/src/main/resources/base/profile/main_pages.json

五、创建项目过程

  1. 打开 DevEco Studio。
  2. 点击 Create Project。
  3. 选择 Application。
  4. 模板选择 Empty Ability。
  5. 开发语言选择 ArkTS。
  6. 模型选择 Stage。
  7. 设置项目名称,例如ArkTSControlsDemo
  8. 选择保存路径,建议路径只包含英文、数字、下划线或连字符。
  9. 选择 API 24+ 对应 SDK。
  10. 点击 Finish,等待工程创建完成。
  11. 打开entry/src/main/ets/pages/Index.ets
  12. 运行默认工程,确认模拟器或真机能打开。
  13. 再逐个添加本文中的页面代码并截图。

六、本次编译安装遇到的问题与解决办法

1. 中文路径导致 Hvigor 拒绝构建

问题现象:

Invalid project path. Current path does not match: D:\私人资料\CSDN\HarmonyOS_ArkTS_API24_ControlsScreenshotApp

原因:Hvigor 对工程路径有限制,路径只能包含英文字母、数字、连字符、下划线、英文句点、英文括号、空格或@

处理办法:把项目复制到 ASCII 路径后构建:

D:\\HarmonyOS_ArkTS_API24_ControlsScreenshotApp

2.DEVECO_SDK_HOME环境变量无效

问题现象:

Invalid value of 'DEVECO_SDK_HOME' in the system environment path.

处理办法:在当前命令会话中临时指定 DevEco SDK 根目录:

$env:DEVECO_SDK_HOME='D:\Program Files\Huawei\DevEco Studio Beta\sdk'

3.hvigor-config.json5缺少dependencies

问题现象:

Schema validate failed ... missingProperty: 'dependencies'

处理办法:补齐hvigor/hvigor-config.json5

{ "modelVersion": "5.0.0", "dependencies": { } }

4. 打包阶段找不到 Java

问题现象:

spawn java ENOENT

处理办法:使用 DevEco Studio 自带 JBR,并停止旧的 Hvigor daemon 后重新构建:

$env:JAVA_HOME='D:\Program Files\Huawei\DevEco Studio Beta\jbr'$env:Path="D:\Program Files\Huawei\DevEco Studio Beta\jbr\bin;$env:Path"hvigorw--stop-daemon

5. 构建成功但有弃用警告

构建时出现过router.pushUrlrouter.backAlertDialog.show的弃用警告,但不影响本次截图 Demo 编译和安装。正式项目建议后续按当前 API 推荐方式替换。

七、本次安装启动记录

构建命令:

hvigorw--mode module-p module=entry@default-p product=default assembleHap

安装命令:

hdc install entry-default-unsigned.hap

启动命令:

hdc shell aastart-a EntryAbility-b com.csdn.arkts.controls.screenshot

验证结果:

  • HAP 构建成功。
  • 模拟器目标:127.0.0.1:5555
  • 安装结果:install bundle successfully
  • 启动结果:start ability successfully