及时做APP开发实战(十三)-已完成数量统计修复
及时做APP开发实战(十三)-已完成数量统计修复本文将介绍如何修复主页面已完成数量不更新的BUG并深入分析ArkTS状态管理机制。一、问题分析1.1 问题现象图 1 问题现象-不及时更新已完成数量┌─────────────────────────────────────┐ │ 待办列表 │ ├─────────────────────────────────────┤ │ ┌─────────────────────────────┐ │ │ │ 进行中 已完成 全部 │ │ │ │ 3 0❌ 5 │ │ ← 已完成数量不更新 │ └─────────────────────────────┘ │ │ │ │ ☐ 学习ArkTS │ │ ☐ 开发及时做APP │ │ ✓ 写博客文档 ← 已完成 │ │ ✓ 代码优化 ← 已完成 │ │ ☐ 测试功能 │ └─────────────────────────────────────┘1.2 问题原因问题代码 ┌─────────────────────────────────────┐ │ Text(this.todoViewModel │ │ .getCompletedTodoCount() │ │ .toString()) │ └─────────────────────────────────────┘ ↓ 调用ViewModel的方法获取数据 ↓ ❌ 不是State变量UI不会自动刷新二、ArkTS状态管理机制2.1 状态变量装饰器装饰器作用触发UI更新State组件内状态✅ 自动更新Prop父→子单向传递✅ 自动更新Link父↔子双向绑定✅ 自动更新Provide跨组件提供✅ 自动更新Consume跨组件消费✅ 自动更新2.2 为什么ViewModel方法不触发更新// ❌ 问题代码Componentstruct Index{StatetodoList:TodoItem[][];privatetodoViewModel:TodoViewModelnewTodoViewModel();build(){Column(){// 调用ViewModel方法Text(this.todoViewModel.getCompletedTodoCount().toString())// ↑ 不是State变量值变化时UI不更新}}}// ✅ 正确代码Componentstruct Index{StatetodoList:TodoItem[][];build(){Column(){// 基于State变量计算Text(this.todoList.filter(itemitem.completed).length.toString())// ↑ 依赖State变量值变化时UI自动更新}}}2.3 状态更新流程┌─────────────────────────────────────┐ │ 状态更新流程 │ ├─────────────────────────────────────┤ │ 1. State变量被修改 │ │ ↓ │ │ 2. ArkTS检测到变化 │ │ ↓ │ │ 3. 触发组件重新渲染 │ │ ↓ │ │ 4. 重新计算依赖该变量的表达式 │ │ ↓ │ │ 5. UI更新显示 │ └─────────────────────────────────────┘三、解决方案3.1 修改前代码// 统计信息组件BuilderStatisticsBar(){Row(){Column(){// ❌ 调用ViewModel方法Text(this.todoViewModel.getActiveTodoCount().toString()).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#FF6B6B)Text(进行中).fontSize(12).fontColor(#666666)}.layoutWeight(1)Column(){// ❌ 调用ViewModel方法Text(this.todoViewModel.getCompletedTodoCount().toString()).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#4CAF50)Text(已完成).fontSize(12).fontColor(#666666)}.layoutWeight(1)Column(){// ✅ 基于State变量Text(this.todoList.length.toString()).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#2196F3)Text(全部).fontSize(12).fontColor(#666666)}.layoutWeight(1)}}3.2 修改后代码// 统计信息组件BuilderStatisticsBar(){Row(){Column(){// ✅ 基于State变量计算Text(this.todoList.filter(item!item.completed).length.toString()).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#FF6B6B)Text(进行中).fontSize(12).fontColor(#666666)}.layoutWeight(1)Column(){// ✅ 基于State变量计算Text(this.todoList.filter(itemitem.completed).length.toString()).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#4CAF50)Text(已完成).fontSize(12).fontColor(#666666)}.layoutWeight(1)Column(){// ✅ 基于State变量Text(this.todoList.length.toString()).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#2196F3)Text(全部).fontSize(12).fontColor(#666666)}.layoutWeight(1)}}3.3 关键改动修改项修改前修改后进行中数量todoViewModel.getActiveTodoCount()todoList.filter(item !item.completed).length已完成数量todoViewModel.getCompletedTodoCount()todoList.filter(item item.completed).length全部数量todoList.lengthtodoList.length不变四、验证修复4.1 测试步骤1. 启动应用进入主页面 ↓ 2. 查看统计栏显示进行中 X已完成 0全部 X ↓ 3. 点击待办项标记为已完成 ↓ 4. 观察统计栏已完成数量应该 1 ↓ 5. 再次点击取消完成状态 ↓ 6. 观察统计栏已完成数量应该 -14.2 预期结果┌─────────────────────────────────────┐ │ 统计栏正确更新 │ ├─────────────────────────────────────┤ │ 操作前进行中 3已完成 0全部 3 │ │ 标记完成进行中 2已完成 1全部 3 │ │ 再标记完成进行中 1已完成 2全部 3 │ │ 取消完成进行中 2已完成 1全部 3 │ └─────────────────────────────────────┘图 2 修复后效果五、最佳实践总结5.1 状态管理原则┌─────────────────────────────────────┐ │ ✅ 状态管理原则 │ ├─────────────────────────────────────┤ │ □ UI显示的数据应依赖State变量 │ │ □ 避免在build()中调用非状态方法 │ │ □ ViewModel方法用于业务逻辑不直接用于UI显示 │ │ □ 使用计算属性/表达式基于State计算 │ └─────────────────────────────────────┘5.2 常见错误模式// ❌ 错误模式1调用方法获取数据Text(this.getData().toString())// ❌ 错误模式2访问非状态变量Text(this.count.toString())// count不是State// ✅ 正确模式基于State计算Text(this.todoList.filter(...).length.toString())六、总结本文修复了主页面已完成数量不更新的BUG核心要点问题原因调用ViewModel方法不触发UI更新解决方案基于State变量计算显示值关键原理ArkTS状态管理机制只有State变量变化才触发UI更新