HarmonyOS +LazyForEach懒加载在删除界面元素时,被删除的元素与当前被选中的不一致

举报
yd_262781458 发表于 2025/08/19 15:54:57 2025/08/19
【摘要】 1.问题说明:使用LazyForEach进行遍历数据,例如:当首次进入,选中列表中第2条数据,点击删除,第二条数据被正常删除;这个时候再次点击当前被刷新之后的列表中的第二条数据,点击删除列表,会出现第二条数据没有被删掉成功。而当前列表中的第三条数据却被删除;2.原因分析:当出现问题时,发现,第一次点击删除正常的前提下,索引传入的值为1,待列表被刷新之后,依然选择第二条数据时,传入的索引变成了...

1.问题说明:

使用LazyForEach进行遍历数据,例如:当首次进入,选中列表中第2条数据,点击删除,第二条数据被正常删除;这个时候再次点击当前被刷新之后的列表中的第二条数据,点击删除列表,会出现第二条数据没有被删掉成功。而当前列表中的第三条数据却被删除;


2.原因分析:

当出现问题时,发现,第一次点击删除正常的前提下,索引传入的值为1,待列表被刷新之后,依然选择第二条数据时,传入的索引变成了2

List(){
      LazyForEach(this.data,(item:string,index:number)=>{
        ListItem(){
          Row() {
            Text(item).fontSize(50)
              .onAppear(() => {
                console.info("Kingson appear:" + item)
              })
          }.margin({ left: 10, right: 10 })
        }.onClick(() => {
          // 点击追加子组件
          this.data.pushData(`Hello ${this.data.totalCount()}`);
        })
        .swipeAction({
          end:{
            builder:()=>{
              this.itemEnd(index);
            },
          }

        })

      },(item: string, index: number)=>item)
    }.cachedCount(5)

3.解决思路:

找出如上index索引传入的值错误的原因;从传入的值来看,无论是第二次、第三次进行点击,获取的index值依然是首次删除前的索引,而非基于当前列表下的最新索引值;虽然数组刷新了,但list中的索引没有变。这个时候就要寻找LazyForEach 混乱的原因

4.解决方案:

LazyForEach 有三个参数,第一个是要传入的集合,第二个是回调,第三个参数是可以影响是否唯一、避免混乱的;最初,第三个参数传入的是:(item: string)=>item,造成了索引混乱,接着改成(item: string, index: number)=>item+index.toString()之后索引的值可以正常改变


具体代码:

BasicDataSource.etc

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

  public totalCount(): number {
    return 0;
  }

  public getData(index: number): 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);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.ADD, index: index}]);
    })
  }

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

  // 通知LazyForEach组件需要在index对应索引处删除该子组件
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.DELETE, index: index}]);
    })
  }

  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
      // 写法2:listener.onDatasetChange(
      //         [{type: DataOperationType.EXCHANGE, index: {start: from, end: to}}]);
    })
  }

  notifyDatasetChange(operations: DataOperation[]): void {
    this.listeners.forEach(listener => {
      listener.onDatasetChange(operations);
    })
  }
}


MyDataSource.etc

@Observed
class MyDataSource extends BasicDataSource {
  @Track dataArray: string[] = [];

  public getDataArr(): string[] {
    return this.dataArray;
  }

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

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

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

  public deleteData(index: number): void {
    this.dataArray.splice(index, 1);
    this.notifyDataDelete(index);
  }

  public reloadData(): void {
    this.notifyDataReload();
  }


}

viewLazyForEachTmp.etc

@Component
export struct viewLazyForEachTmp{
  pathStack: NavPathStack = new NavPathStack();
  private data: MyDataSource = new MyDataSource();

  @State arrList:Array<string>=["1","2"]

  aboutToAppear() {
    for (let i = 0; i <= 10; i++) {
      this.data.pushData(`Hello ${i}`)
      this.arrList.push(`Hello ${i}`)
    }
  }

  @Builder itemEnd(index: number) {
    // 构建尾端滑出组件
    Button({ type: ButtonType.Normal }) {
      Text("删除")
        .width("25%")
        .height("100%")
        .backgroundColor("#ff00")
        .fontSize(14)
        .fontColor("#ffffff")
        .textAlign(TextAlign.Center)
    }
    .onClick(() => {
      // this.messages为列表数据源,可根据实际场景构造。点击后从数据源删除指定数据项。
      this.data.deleteData(index)
      // 重置所有子组件的index索引
      this.data.reloadData();
      console.info("Kingson     删除  index->"+index)
      console.info("Kingson     删除  index->"+JSON.stringify(this.data.getDataArr()))
    })
  }

  build() {
    NavDestination(){

    List(){
      LazyForEach(this.data,(item:string,index:number)=>{
        ListItem(){
          Row() {
            Text(item).fontSize(50)
              .onAppear(() => {
                console.info("Kingson appear:" + item)
              })
          }.margin({ left: 10, right: 10 })
        }.onClick(() => {
          // 点击追加子组件
          this.data.pushData(`Hello ${this.data.totalCount()}`);
        })
        .swipeAction({
          end:{
            builder:()=>{
              this.itemEnd(index);
            },
          }

        })

      },(item: string, index: number)=>item+index.toString())
    }.cachedCount(5)






    }.title("懒加载")
    .onBackPressed(() => {
      const popDestinationInfo = this.pathStack.pop(); // 弹出路由栈栈顶元素
      console.info('pop' + '返回值' + JSON.stringify(popDestinationInfo));
      return true
    })
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
    })
  }
}







借鉴:LazyForEach:数据懒加载
















【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。