ArkTS “一篇带你读懂ForEach和LazyForEach” 【小白拓展】

ArkTS “一篇带你读懂ForEach和LazyForEach”【小白拓展】



前言

列表是应用开发中最常见的一类开发场景,它可以将杂乱的信息整理成有规律、易于理解和操作的形式,便于用户查找和获取所需要的信息。

在现有的较成熟ArkTs组件中的,推荐大家使用的列表渲染接口是ForEach和LazyForEach。


一、原理介绍

HarmonyOS应用框架为容器类组件的数据加载和渲染提供了2种方式。

方式一,循环渲染
通过循环渲染(ForEach)从数组中获取数据,并为每个数据项创建相应的组件,可减少代码复杂度。

代码如下(示例)详解可以看上一篇:

ForEach(
  arr: any[], 
  itemGenerator: (item: any, index?: number) => void,
  keyGenerator?: (item: any, index?: number) => string 
)

方式二,数据懒加载
通过数据懒加载(LazyForEach)从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件

使用步骤如下(重点详解):

DataSource: Data<string>=new Data<string>()
LazyForEach(
  dataSource: DataSource, (这里要求数据源一定要实现IDataSource接口)            
  itemGenerator: (item: any) => void,  
  keyGenerator?: (item: any) => string //可省
): void

class Data implements IDataSource{
 **//我们使用需要自己创建**
  private originArr:string[]=[]   //用来存储数据
  private listeners:DataChangeListener[] = []  //用来存储监听
  
  //自定义添加数据方法
  addData(data:string[]){
	let indexs=this.totalCount()
    this.originArr.push(...data)
    this.listeners.forEach(listener=>listener.onDataAdd(indexs))
  }
 **//IDataSource内置方法** 
  totalCount(): number {
    return this.originArr.length  //返回数据长度
  };                                         
  getData(index: number): T{
    return this.originArr[index]  //返回索引值index对应的数据
  };                                   
  	//注册 数据改变的监听器
  registerDataChangeListener(listener: DataChangeListener): void{
  //把注册的监听器放入列表
	 if (this.listeners.indexOf(listener) < 0) {
     console.info('add listener');
     this.listeners.push(listener);
   }
  };
  	//注销 数据改变的监听器   
  unregisterDataChangeListener(listener: DataChangeListener): void{
   //把已经注册的监听器从列表移除
   const pos = this.listeners.indexOf(listener);
   if (pos >= 0) {
     console.info('remove listener');
     this.listeners.splice(pos, 1);
   	 }
   };
}


//下面是DataChangeListener数据变化监听器 内置方法我们可能会用到的
interface DataChangeListener {
  onDataReloaded(): void;              //通知组件重新加载所有数据        
  onDataAdd(index: number): void;      //通知组件index的位置有数据添加。
  onDataMove(from: number, to: number): void; //通知组件数据有移动。将from和to位置的数据进行交换。
  onDataDelete(index: number): void;        //通知组件删除index位置的数据并刷新LazyForEach的展示内容。
  onDataChange(index: number): void;       //通知组件index的位置有数据有变化。
}

二、ForEach是怎么实现渲染的?

从华为文档我们可知

  1. 从列表数据源 一次性加载全量 数据。
  2. 为列表数据的每一个元素都创建对应的组件,并全部挂载在组件树上。即,ForEach遍历多少个列表元素,就创建多少个ListItem组件节点并依次挂载在List组件树根节点上。
  3. 列表内容显示时,只渲染屏幕可视区内的ListItem组件,可视区外的ListItem组件滑动进入屏幕内时,因为已经完成了数据加载和组件创建挂载,直接渲染即可。
    在这里插入图片描述
    数据量大时会非常耗时,会导致页面启动时间过长、过多占用内存。在系统处于高负载的情况下,更容易出现性能问题,极限情况下甚至会导致应用异常退出。

所以,ForEach适合少量数据渲染

三、LazyForEach是怎么实现渲染的?

  1. LazyForEach会根据屏幕可视区能够容纳显示的组件数量按需加载数据。
  2. 当可视区外的组件需要在屏幕内显示时,需要从头完成数据加载、组件创建、挂载组件树这一过程,直至渲染到屏幕上。

概括来说就是,按需加载

针对列表数据量大、列表组件复杂的场景,减少了页面首次启动时一次性加载数据的时间消耗,减少了内存峰值,优化了性能。

我们该怎么选择他们呢

ForEach列表数据较少,数据一次性全量加载不是性能瓶颈时
LazyForEach列表数据较长,一次性加载所有的列表数据创建、渲染页面产生性能瓶颈时

四、值得注意的使用小tips

1.关于ForEach

ForEach在下列容器组件 List、Grid、Swiper以及WaterFlow 内使用的时候,不要与LazyForEach 混用。

2.关于LazyForEach

LazyForEach必须在容器组件内使用,仅有 List、Grid、Swiper 以及 WaterFlow 组件支持数据懒加载


总结

以上就是今天要讲的内容,请大家注意LazyForEach的使用,较为复杂。具体的大家有疑问可以留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值