在鸿蒙中使用 Repeat 渲染嵌套列表,修改内层列表的一个元素,页面不会更新

问题:在鸿蒙中使用 Repeat 渲染嵌套列表,修改内层列表的一个元素,页面不会更新

数据结构如下:

yaml 复制代码
  interface IListData {
    id: number,
    name: string,
  }

  listData: [
    {
      id: 1,
      name: 'A',
      list: [
        {
          id: 1,
          name: '张三'
        },
        {
          id: 2,
          name: '李四'
        }
      ]
    }
  ]

渲染代码如下:

scss 复制代码
  List({ space: 20 }) {
    Repeat(this.listData).each((ri: RepeatItem<IReportListResponse_list>) => {
      ListItem() {
        Column() {
          Text(this.handleNursingTime(ri.item.name))
            .fontColor('#333333')
            .fontSize('16fp')
            .margin({ bottom: 10 })
          Column() {
            Repeat(ri.item.nursingModelInfoList).each((riChild: RepeatItem<INursingModelInfo>) => {
              Row() {
                Text(this.handleNursingTime(riChild.item.name))
            }).key((item: INursingModelInfo, index) => `${item.id}`)
          }
          .backgroundColor(Color.White)
          .borderRadius(12)
        }
        .alignItems(HorizontalAlign.Start)
      }
    }).key((item: IReportListResponse_list, index) => `${item.id}`)

调用方法删除内层列表的一个元素:

typescript 复制代码
  deleteByReportIndex(id: number) {
    const arr = this.listData.map((item) => {
      item.list = item.list.filter((childItem) => {
        return childItem.id !== id;
      })
      return item;
    })

    this.listData = arr.filter((item) => {
      return item.list.length > 0;
    })
  }

此时内层的元素已被删除了一个,但是页面不会更新

如何解决这个问题?

在 HarmonyOS Next 的状态管理 V2 (@ObservedV2 + @Trace) 中,最核心的规则是:只有真正的类实例(Class Instance)才能被观测,普通的 JSON 对象即便赋值给被装饰的变量,也无法触发深度监听。

直接将接口返回的 JSON 对象赋值给了 this.listData,没有实例化 IListData 类。导致 @Trace 装饰器完全失效,ArkUI 把它当做普通对象处理,所以修改内层数据无法驱动 UI 刷新。

解决方案

  1. 为了让内层列表渲染更稳定,建议给内层的数据也定义一个 @ObservedV2 的类。
ini 复制代码
  interface IList {
    id: number;
    name: string;
  }

  @ObservedV2
  class IListData {
    id: number;
    name: string;
    @Trace list: IList[];
    constructor(id: number, name: string, list: IList[]) {
      this.id = id;
      this.name = name;
      this.list = IList;
    }
  }
  1. 在接口请求回来后,必须用 new 关键字转换数据。
kotlin 复制代码
export struct HistoryList {
  @Local listData: IListData[] = [];

  async fetchData(): Promise<void> {
    const res: AxiosResponse<IBaseResponse<ReportListResponse>> = await getReportList(1, this.pageSize);
    if (res.data.success) {
      this.data = res.data.data;
      this.listData = res.data.data.list.map((item: IReportListResponse_list) => {
        // 这里必须 new 你的类
        return new IListData(item.id, item.name, item.list);
      });
    }
  }

  build(){

  }
}
  1. 这样,当你修改 listData 中的任何一个元素时,UI 都会自动更新。
相关推荐
喵个咪9 小时前
一套Schema,生成全部代码|Kratos高效开发新范式
前端·后端·架构
Dewyze同学9 小时前
我用 Cursor 三天从零到可上线:uni-app + Fastify 全栈小程序复盘
前端
qq_381338509 小时前
前端虚拟列表与无限滚动性能优化实战:从万级数据到丝滑体验
前端·javascript·html·优化
hexu_blog9 小时前
前端vue后端springboot如何实现图片格式转换
前端·javascript·vue.js
代码煮茶9 小时前
Vue3 项目规范实战 | ESLint+Prettier+Git Hooks 搭建前端代码规范体系
前端·javascript·vue.js
米丘9 小时前
新一代代码格式化工具 Oxfmt/Oxlint
前端·rust·前端工程化
韭菜炒大葱9 小时前
讲讲 浏览器的缓存机制
前端·面试·浏览器
AI砖家9 小时前
DeepSeek TUI 保姆级安装配置全指南 -Windows||macOS双平台全覆盖
服务器·前端·人工智能·windows·macos·ai编程·策略模式
Apache01210 小时前
chrome调试打开,让AI来操作浏览器
前端·chrome
lbaihao10 小时前
LLVM Cpu0 调用规则解析
开发语言·前端·python·llvm