鸿蒙Next数据懒加载LazyForEach用法总结

[复制链接]
发表于 2025-12-4 12:27:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
在鸿蒙Next开辟中,LazyForEach提供了高效的数据懒加载机制,实用于处置惩罚大量数据的列表展示等场景,可有用提拔性能和内存管理。以下是其详细用法总结。
一、利用限定


  • 容器组件要求:必须在特定容器组件(List、Grid、Swiper、WaterFlow)内利用,且这些组件支持设置cachedCount属性实现按需加载。
  • 数目限定:容器组件内只能包罗一个LazyForEach。
  • 子组件规则:每次迭代必须且只能创建一个子组件,且天生的子组件必须符合父容器组件对子组件的要求。
  • 条件渲染支持:允许包罗在if/else条件渲染语句中,也可在其内部出现if/else条件渲染语句。
  • 键值唯一性:键值天生器必须为每个数据天生唯一值,否则会导致UI组件渲染题目。
  • 更新方式限定:必须利用DataChangeListener对象更新,对第一个参数dataSource重新赋值会非常,且dataSource利用状态变量时,状态变量改变不会触发UI革新。为高性能渲染,需通过onDataChange方法更新UI并天生差别键值触发组件革新。
  • 装饰器要求:必须和@Reusable装饰器一起利用才气触发节点复用,需将@Reusable装饰在LazyForEach列表的组件上。
二、键值天生规则


  • 体系默认规则:若开辟者未界说keyGenerator函数,ArkUI框架利用默认函数(item: Object, index: number) => { return viewId + '-' + index.toString(); }(viewId在编译器转换过程中天生,同一个LazyForEach组件内其viewId划一)。
  • 自界说规则:开辟者可通过提供keyGenerator函数来自界说键值天生逻辑。
三、组件创建规则

1. 初次渲染


  • 天生差别键值:根据键值天生规则为数据源每个数组项天生唯一键值并创建组件。
  • 示例:
  1. class BasicDataSource implements IDataSource {
  2.   // 省略部分代码...
  3. }
  4. class MyDataSource extends BasicDataSource {
  5.   // 省略部分代码...
  6. }
  7. @Entry
  8. @Component
  9. struct MyComponent {
  10.   private data: MyDataSource = new MyDataSource();
  11.   aboutToAppear() {
  12.     for (let i = 0; i <= 20; i++) {
  13.       this.data.pushData(`Hello ${i}`)
  14.     }
  15.   }
  16.   build() {
  17.     List({ space: 3 }) {
  18.       LazyForEach(this.data, (item: string) => {
  19.         ListItem() {
  20.           Row() {
  21.             Text(item).fontSize(50)
  22.             .onAppear(() => {
  23.                 console.info("appear:" + item)
  24.               })
  25.           }.margin({ left: 10, right: 10 })
  26.         }
  27.       }, (item: string) => item)
  28.     }.cachedCount(5)
  29.   }
  30. }
复制代码

  • 上述代码中,键值天生规则为item,为数据源数组项依次天生键值Hello 0、Hello 1等,并创建对应的ListItem子组件渲染到界面。
  • 键值类似时错误渲染:差别数据项天生类似键值时,框架举动不可猜测。比方,当全部数据项键值类似时,滑动过程中大概因框架取用缓存错误导致子组件渲染题目。
2. 非初次渲染


  • 当数据源变革时,开辟者需根据变革环境调用listener对应的接口关照LazyForEach更新,包罗添加、删除、交换数据和改变单个数据等利用。
  • 添加数据:
  1. class BasicDataSource implements IDataSource {
  2.   // 省略部分代码...
  3. }
  4. class MyDataSource extends BasicDataSource {
  5.   // 省略部分代码...
  6. }
  7. @Entry
  8. @Component
  9. struct MyComponent {
  10.   private data: MyDataSource = new MyDataSource();
  11.   aboutToAppear() {
  12.     for (let i = 0; i <= 20; i++) {
  13.       this.data.pushData(`Hello ${i}`)
  14.     }
  15.   }
  16.   build() {
  17.     List({ space: 3 }) {
  18.       LazyForEach(this.data, (item: string) => {
  19.         ListItem() {
  20.           Row() {
  21.             Text(item).fontSize(50)
  22.             .onAppear(() => {
  23.                 console.info("appear:" + item)
  24.               })
  25.           }.margin({ left: 10, right: 10 })
  26.         }
  27.        .onClick(() => {
  28.           // 点击追加子组件
  29.           this.data.pushData(`Hello ${this.data.totalCount()}`);
  30.         })
  31.       }, (item: string) => item)
  32.     }.cachedCount(5)
  33.   }
  34. }
复制代码

  • 点击子组件时,调用数据源的pushData方法添加数据并关照LazyForEach,LazyForEach会在相应索引处新建子组件。
  • 删除数据:
  1. class BasicDataSource implements IDataSource {
  2.   // 省略部分代码...
  3. }
  4. class MyDataSource extends BasicDataSource {
  5.   // 省略部分代码...
  6. }
  7. @Entry
  8. @Component
  9. struct MyComponent {
  10.   private data: MyDataSource = new MyDataSource();
  11.   aboutToAppear() {
  12.     for (let i = 0; i <= 20; i++) {
  13.       this.data.pushData(`Hello ${i}`)
  14.     }
  15.   }
  16.   build() {
  17.     List({ space: 3 }) {
  18.       LazyForEach(this.data, (item: string, index: number) => {
  19.         ListItem() {
  20.           Row() {
  21.             Text(item).fontSize(50)
  22.             .onAppear(() => {
  23.                 console.info("appear:" + item)
  24.               })
  25.           }.margin({ left: 10, right: 10 })
  26.         }
  27.        .onClick(() => {
  28.           // 点击删除子组件
  29.           this.data.deleteData(this.data.dataArray.indexOf(item));
  30.         })
  31.       }, (item: string) => item)
  32.     }.cachedCount(5)
  33.   }
  34. }
复制代码

  • 点击子组件时,调用数据源的deleteData方法删除数据并关照LazyForEach,LazyForEach会在相应索引处删除子组件。
  • 交换数据:
  1. class BasicDataSource implements IDataSource {
  2.   // 省略部分代码...
  3. }
  4. class MyDataSource extends BasicDataSource {
  5.   // 省略部分代码...
  6. }
  7. @Entry
  8. @Component
  9. struct MyComponent {
  10.   private moved: number[] = [];
  11.   private data: MyDataSource = new MyDataSource();
  12.   aboutToAppear() {
  13.     for (let i = 0; i <= 20; i++) {
  14.       this.data.pushData(`Hello ${i}`)
  15.     }
  16.   }
  17.   build() {
  18.     List({ space: 3 }) {
  19.       LazyForEach(this.data, (item: string, index: number) => {
  20.         ListItem() {
  21.           Row() {
  22.             Text(item).fontSize(50)
  23.             .onAppear(() => {
  24.                 console.info("appear:" + item)
  25.               })
  26.           }.margin({ left: 10, right: 10 })
  27.         }
  28.        .onClick(() => {
  29.           this.moved.push(this.data.dataArray.indexOf(item));
  30.           if (this.moved.length === 2) {
  31.               // 点击交换子组件
  32.               this.data.moveData(this.moved[0], this.moved[1]);
  33.             this.moved = [];
  34.           }
  35.         })
  36.       }, (item: string) => item)
  37.     }.cachedCount(5)
  38.   }
  39. }
复制代码

  • 初次点击子组件记载索引,再次点击时调用数据源的moveData方法移动数据并关照LazyForEach,LazyForEach会交换相应索引处的子组件位置。
  • 改变单个数据(示例代码未完备给出改变单个数据的关照逻辑,假设已有相应方法):类似其他利用,需在数据源中修改数据并通过符合的listener方法关照LazyForEach,以触发对应子组件的更新。
四、常见利用题目

1. 渲染效果非预期


  • 如键值天生规则不公道或数据源利用与关照不匹配,大概导致渲染效果不符合预期。
2. 重渲染时图片闪耀


  • 大概由于组件更新过程中图片加载或处置惩罚不妥导致,需优化图片相干利用或查抄组件更新逻辑。
3. @ObjectLink属性变革UI未更新


  • 大概是未准确利用相干装饰器或数据绑定机制,需确保@ObjectLink等装饰器的准确利用及数据的准确转达与更新。
4. 在List内利用屏幕闪耀


  • 大概与List组件的设置、LazyForEach的更新机制或其他因素有关,可查抄List组件属性设置、数据更新频率及装备性能等方面。
利用LazyForEach时,需严格遵照其利用限定,公道界说键值天生规则,准确处置惩罚数据源变革关照,同时留意常见题目的排查与办理,以充实发挥其数据懒加载上风,提拔应用性能与用户体验。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表