HarmonyOS Next懒加载组件复用

        因为项目可能会在后期要求渲染较多的数据项,且可能用于不同页面,故依据Api12的官方文档做了一个简单的懒加载组件,首先第一步是完成类的封装,这里的BasicData是对官方文档里面的直接复制,但这里对我们要使用的ProductInfoSource 这个类添加了一个更贴合我的项目的更改,我们加入了pushDataList来实现对数组的拼接。

class BasicDataSource implements IDataSource {
  private listeners: DataChangeListener[] = [];
  private originDataArray: Data[] | string[] = [];

  public totalCount(): number {
    return 0;
  }

  public getData(index: number): Data | string {
    return this.originDataArray[index];
  }

  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener');
      this.listeners.push(listener);
    }
  }

  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    })
  }

  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
    })
  }

  // 通知LazyForEach组件需要在index对应索引处删除该子组件
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
    })
  }

  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
    })
  }
}
@Observed class ProductInfoSource extends BasicDataSource {
  private dataArray: Data[] = [];

  public totalCount(): number {
    return this.dataArray.length;
  }

  public getData(index: number): Data {
    return this.dataArray[index];
  }

  public addData(index: number, data: Data): void {
    this.dataArray.splice(index, 0, data);
    this.notifyDataAdd(index);
  }

  public pushData(data: Data): void {
    this.dataArray.push(data);
    this.notifyDataAdd(this.dataArray.length - 1);
  }

  public pushDataList(data: Data[]): void {
    // 添加新数据
    const startIndex = this.dataArray.length;
    this.dataArray = [...this.dataArray, ...data];
    // 通知每个新增数据项
    for (let i = 0; i < data.length; i++) {
      this.notifyDataAdd(startIndex + i);
    }
  }
}

然后编写子组件,这里只是简单的完成子组件的功能,之前使用@Prop装饰器一直无法正确渲染,后面找到了原因。
 

import { Data, ProductInfoSource } from '../interface/TypeFile'
@Component
export struct ProductItem {
  // @State装饰器只能观察到第一层属性,这里使用@Prop无法更新数据
  @ObjectLink data: ProductInfoSource;
  // 若还有需要可以使用占位符实现row内容的替换
  // 例如@BuilderParam Row_: () => void;
  // 在build中使用this.Row_()实现对懒加载组件的复用
  build() {
    List({ space:10 }) {
      LazyForEach(this.data, (item: Data) => {
        ListItem() {
          Row() {
            Image((item.cover as Data[])[0].source as string)
            Text(JSON.stringify(item))
          }
        }
      })
    }
  }
}

然后在父组件中引用该组件就可以正常渲染了

build()
{    
    // .......
    ProductItem({ data: this.productData })
    // .......
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值