文章目录前言先想清楚要什么数据模型 存储代码实现主页面列表 状态列表项勾选 删除 动画增与删这个 App 用到了哪些知识常见误区小白必踩完整可运行示例待办 App 的持久化核心代码写在最后前言本篇我们主要做的是从零做一个能跑的待办事项 App——增、删、改、持久化、动画、主题全用上。做完这个你对 HarmonyOS 开发会有整体感。代码我分模块给你跟着敲就能跑。先想清楚要什么一个待办 App 的最小功能列表展示待办项标题、是否完成新增待办勾选完成带过渡动画删除待办数据持久化关掉再开还在深色模式切换顺手加数据模型 存储用Preferences存简单列表前面讲过的。先定义模型代码实现interfaceTodo{id:numbertitle:stringdone:boolean}// 存储封装import{preferences}fromkit.ArkDataletprefs:preferences.PreferencesasyncfunctioninitStore(){prefsawaitpreferences.getPreferences(getContext(),todo)}asyncfunctionsave(list:Todo[]){awaitprefs.put(list,JSON.stringify(list))awaitprefs.flush()}asyncfunctionload():PromiseTodo[]{constsawaitprefs.get(list,[])asstringreturnJSON.parse(s)asTodo[]}用 JSON 把数组序列化存进 Preferences简单够用。save写完必须flush否则重启丢失老坑了。主页面列表 状态EntryComponentV2struct TodoApp{Localtodos:Todo[][]Localinput:stringLocaldark:booleanfalseaboutToAppear(){initStore().then(()load()).then(listthis.todoslist)}build(){Column(){// 顶部标题 主题切换Row(){Text(我的待办).fontSize(22).fontWeight(FontWeight.Bold)Blank()Toggle({type:ToggleType.Switch,isOn:this.dark}).onChange(vthis.darkv)}.padding(12)// 输入区Row(){TextInput({placeholder:写点什么...,text:this.input}).onChange(vthis.inputv).layoutWeight(1)Button(添加).onClick(()this.add())}.padding({left:12,right:12,bottom:8})// 列表List(){ForEach(this.todos,(t:Todo){ListItem(){this.TodoRow(t)}},(t:Todo)t.id.toString())}.layoutWeight(1)}.backgroundColor(this.dark?#1A1A1A:#F5F5F5).width(100%).height(100%)}}讲解aboutToAppear里初始化存储并加载已有数据。ForEach渲染列表用id当唯一键重要前面踩坑篇讲过。主题切换直接改dark状态根背景随之变化。列表项勾选 删除 动画BuilderTodoRow(t:Todo){Row(){Checkbox({name:t.id.toString(),group:todo}).select(t.done).onChange(vthis.toggle(t.id,v))Text(t.title).fontSize(16).decoration({type:t.done?TextDecorationType.LineThrough:TextDecorationType.None}).fontColor(t.done?#999999:(this.dark?#EEEEEE:#333333)).layoutWeight(1)Button(删).onClick(()this.remove(t.id))}.padding(12).backgroundColor(this.dark?#2A2A2A:#FFFFFF).borderRadius(8).margin({left:12,right:12,bottom:8})}toggle(id:number,done:boolean){animateTo({duration:250,curve:Curve.EaseOut},(){this.todosthis.todos.map(tt.idid?{...t,done}:t)})this.persist()}Checkbox勾选触发toggle用animateTo让划线 变灰平滑过渡。decoration给完成的项加删除线视觉反馈清晰。改完立刻persist()存盘。增与删add(){if(!this.input.trim())returnconstitem:Todo{id:Date.now(),title:this.input.trim(),done:false}this.todos[item,...this.todos]// 新项置顶this.inputthis.persist()}remove(id:number){animateTo({duration:200},(){this.todosthis.todos.filter(tt.id!id)})this.persist()}persist(){save(this.todos)// 防抖可后续优化}新增用Date.now()当唯一 id够用且天然唯一。删除用filter配合animateTo有消失动画。每次变更都persist()落盘保证持久化。这个 App 用到了哪些知识能力来自哪篇Column/Row 布局布局篇Local 状态驱动状态原理篇ForEach 唯一键列表踩坑篇Checkbox/TextInput/Toggle表单组件animateTo 动画属性动画篇Preferences 存储轻量存储篇aboutToAppear 初始化生命周期篇主题切换深色模式篇你看一个看似完整的小 app就是把前面零散的知识点拼起来。这就是实战的意义知识不再是孤岛。常见误区小白必踩误区说明唯一键用下标ForEach用下标当键删除会错乱用id如Date.now()当唯一键。改完不flushPreferences 存待办忘了flush重启数据全丢。勾选用animateTo套错对象动画要包在状态变更上包错地方就没过渡效果。主题不持久化深色模式切换后没存 Preferences下次打开又回浅色。下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲改一改文末「动手改一改」里的参数亲眼看看效果。完整可运行示例待办 App 的持久化把前面综合实战里的待办数据落盘关掉 App 再开数据还在。核心代码// 用 Preferences 持久化待办列表import{preferences}fromkit.ArkDataasyncfunctionsaveTodos(list:string[]){constprefawaitpreferences.getPreferences(getContext(),todo)awaitpref.put(list,JSON.stringify(list))// 数组序列化后存awaitpref.flush()}asyncfunctionloadTodos():Promisestring[]{constprefawaitpreferences.getPreferences(getContext(),todo)constspref.get(list,[])asstringreturnJSON.parse(s)asstring[]}你会看到什么在综合实战的待办 App 里接上这两个函数——新增待办后调用saveTodosaboutToAppear时调用loadTodos恢复。这样即使杀掉进程下次打开待办仍在。动手改一改把Preferences换成relationalStore支持「按完成状态筛选」。给每条待办加id与done字段做「已完成划线」。用分布式 KV 把待办同步到平板体验多端一致。写在最后这个待办 App 虽小却是 HarmonyOS 开发的微缩全景——布局、状态、列表、动画、存储、主题全齐了。建议你别只是看把代码敲进 DevEco 真跑一遍再自己加个功能比如编辑待办“按完成筛选”。当你能把零散知识拼成完整产品才算真正入门 HarmonyOS 开发。