一、为什么用一个“小而完整”的待办面板练习鸿蒙 ArkUI在鸿蒙 PC 场景中页面不是把手机界面横向拉宽即可。窗口变大后用户通常希望同时看到分类入口、当前任务和完成进度如果还依赖多层跳转操作成本反而会上升。待办面板正好覆盖一个业务页面最常见的闭环数据建模 → 页面状态 → 分类筛选 → 列表渲染 → 用户交互 → 状态回写。示例包含以下能力左侧显示“全部、进行中、已完成”三个筛选入口右侧用任务卡片展示标题与完成状态点击分类后只展示符合条件的任务勾选复选框后任务文本颜色和删除线随状态更新采用“左导航 右内容”的宽屏布局让页面层级保持清晰。它不是要替代完整的任务管理产品而是提供一个可以继续扩展的 ArkUI 页面骨架。后续接入本地持久化、网络数据、搜索和任务创建时不需要推翻核心状态结构。二、先确定数据边界只保存源数据和筛选条件每条任务只保留三个字段唯一标识id、展示用title和完成状态done。页面状态中只维护原始任务数组todos与筛选条件filterinterfaceTodoItem{id:numbertitle:stringdone:boolean}Statetodos:TodoItem[][{id:1,title:整理鸿蒙 PC 文章大纲,done:false},{id:2,title:运行示例并截取页面,done:false},{id:3,title:检查发布前质量分,done:true}]Statefilter:string全部这里有一个容易被忽略的原则不要把“全部列表”“进行中列表”“已完成列表”分别存成三份状态。三份列表一旦同时存在勾选任务后就必须同步修改多个位置很容易出现计数不一致或切换分类后显示旧数据的问题。更稳妥的做法是只保存源数据再根据当前筛选条件推导出页面需要展示的数据privategetvisibleTodos():TodoItem[]{if(this.filter进行中)returnthis.todos.filter(item!item.done)if(this.filter已完成)returnthis.todos.filter(itemitem.done)returnthis.todos}visibleTodos是从todos和filter计算出来的结果不承担额外的数据写入职责。这样无论用户先切换筛选还是先勾选任务最终界面都从同一个源数组推导逻辑更容易验证。三、完整页面代码导航、列表和交互放在同一个状态闭环里将下面代码放入 ArkTS Stage 工程首页的Index.ets后可以作为页面原型继续扩展interfaceTodoItem{id:numbertitle:stringdone:boolean}EntryComponentstruct Index{Statetodos:TodoItem[][{id:1,title:整理鸿蒙 PC 文章大纲,done:false},{id:2,title:运行示例并截取页面,done:false},{id:3,title:检查发布前质量分,done:true}]Statefilter:string全部privategetvisibleTodos():TodoItem[]{if(this.filter进行中)returnthis.todos.filter(item!item.done)if(this.filter已完成)returnthis.todos.filter(itemitem.done)returnthis.todos}build(){Row(){this.Sidebar()this.ContentPanel()}.width(100%).height(100%).backgroundColor(#F6F8FA)}BuilderSidebar(){Column({space:12}){Text(我的待办).fontSize(24).fontWeight(FontWeight.Bold)ForEach([全部,进行中,已完成],(item:string){Text(item).width(100%).padding(12).borderRadius(8).backgroundColor(this.filteritem?#DCEBFF:#FFFFFF).onClick(()this.filteritem)})}.width(180).height(100%).padding(20).backgroundColor(#FFFFFF)}BuilderContentPanel(){Column({space:16}){Text(this.filter).fontSize(28).fontWeight(FontWeight.Bold)Text(共${this.visibleTodos.length}条任务).fontSize(14).fontColor(#667085)List({space:10}){ForEach(this.visibleTodos,(item:TodoItem){ListItem(){Row({space:12}){Checkbox({name:String(item.id),group:todos}).select(item.done).onChange((value:boolean)this.toggleTodo(item.id,value))Text(item.title).fontSize(17).fontColor(item.done?#98A2B3:#1D2939).decoration({type:item.done?TextDecorationType.LineThrough:TextDecorationType.None})}.width(100%).padding(18).borderRadius(12).backgroundColor(#FFFFFF)}},(item:TodoItem)item.id)}.layoutWeight(1)}.layoutWeight(1).height(100%).padding({left:32,right:32,top:28,bottom:28})}privatetoggleTodo(id:number,done:boolean):void{this.todosthis.todos.map(itemitem.idid?{...item,done}:item)}}四、三个关键实现点1. 用State管理会影响界面的数据todos和filter都会直接影响 UI前者决定任务卡片内容和勾选状态后者决定展示范围。因此它们适合作为页面状态。点击分类时只需要更新filter列表读取visibleTodos后就会根据新的条件展示对应任务。状态粒度要适中。把每一个派生结果也放入状态不会让页面更“响应式”反而会让同步关系变复杂。保留最少、最权威的状态能降低维护成本。2. 更新任务时返回新数组而不是隐式修改旧对象勾选复选框时示例通过map生成新的任务数组privatetoggleTodo(id:number,done:boolean):void{this.todosthis.todos.map(itemitem.idid?{...item,done}:item)}这段代码有两个好处第一只有id相同的目标任务会被替换第二最终会把新的数组赋回State字段状态变化的入口非常明确。以后如果要记录修改时间、增加撤销操作或写入持久化层也能在这个方法里集中处理。3. 宽屏布局先保证信息层级再考虑视觉细节左侧导航使用固定宽度右侧内容区通过layoutWeight(1)占据剩余空间。这个组合的目的不是追求复杂布局而是让用户一眼看清三类信息当前位置左侧哪个筛选项被选中当前范围右侧标题与“共 X 条任务”可执行内容列表中的任务和复选框。任务卡片采用留白、圆角和弱对比背景已完成任务降低文字对比度并加删除线。即使任务数量增加阅读顺序也不会混乱。五、真实运行前的验证清单下面步骤用于得到可用于文章的真实运行截图。在未完成这些步骤前不应把页面描述为“运行成功”。在 DevEco Studio 创建或打开 ArkTS Stage 工程用本文代码替换首页Index.ets处理工程模板与 SDK 版本可能带来的编译提示将工程运行到可用的鸿蒙 PC 模拟器或真实设备截取完整初始布局左侧导航、右侧标题、统计文字和三张任务卡都应可见点击“进行中”确认列表只保留未完成任务再截取筛选状态勾选一条未完成任务确认任务从“进行中”列表移除或在“全部”中呈现完成样式再截取交互后的状态对照截图与本文任务文案、数量和交互说明确认一致后再插入 CSDN 正文。真实运行截图六、可以继续扩展什么当页面原型完成真实验证后可以按业务优先级继续增加创建任务用输入框或弹窗生成新的TodoItem搜索任务把搜索关键字作为另一个状态并与filter共同推导展示列表持久化把任务数组保存到本地数据层在页面初始化时恢复任务优先级在数据模型中加入优先级字段并通过颜色或排序强化信息层级跨设备能力在明确业务需求和数据一致性策略后再考虑同步机制。扩展时仍应遵守同一原则源数据尽量单一界面结果尽量通过源数据和当前条件推导而不是在多个组件之间复制状态。七、小结这个鸿蒙 ArkUI 待办面板的重点不是功能数量而是形成一条可复用的页面开发路径数据建模 → 状态保存 → 派生筛选 → 列表渲染 → 交互更新 → 真实运行验证。只要保持状态来源清晰后续无论是增加搜索、创建任务还是接入网络数据都可以在现有结构上继续演进。发布前最后一步也不能省略必须用真实设备或模拟器运行项目、截取与本文描述一致的画面并把截图嵌入文章正文。