HarmonyOS鸿蒙Next中使用LazyForEach做分页查询刷新列表,把数据pushData后,出现页面跳到第一条数据的bug,如何解决

HarmonyOS鸿蒙Next中使用LazyForEach做分页查询刷新列表,把数据pushData后,出现页面跳到第一条数据的bug,如何解决

关键代码如下

Refresh({refreshing: $$this.isRefreshing, builder: this.customRefreshComponent()}){
  List(){
    LazyForEach(this.orderListData,(item: ShopDeviceOrderListContent)=>{
      OrderListItem({orderInfo: item, copy:  (id: string)=> { this.onCopy(id) }})
        .width('93%').margin({top: 10}).borderRadius(16).shadow(ShadowStyle.OUTER_DEFAULT_SM)
    }, (item: ShopDeviceOrderListContent) =>   item.id)

    ListItem(){
      Text("没有更多数据")
        .fontSize(16)
        .fontColor($r('app.color.colorText3'))
        .width('100%')
        .height(40)
        .textAlign(TextAlign.Center)
        .visibility(this.noMoreShow && this.orderListData.totalCount() > 0 ? Visibility.Visible : Visibility.None)
    }
  }
  .width('100%')
  .height('100%')
  .alignListItem(ListItemAlign.Center)
  .onReachEnd(()=>{
    if (!this.noMoreShow){
      this.initData()
    }
  })
}
.onRefreshing(()=>{
  this.query.page = 0
  this.initData()
})
initData(){
  if (this.loading){
    return
  }
  this.loading = true
  efRcpClientApi.get<ShopDeviceOrderListData>({
    url: deviceOrder,
    query: this.query,
    isParams: true
  }).then((data)=>{
    if (this.query.page == 0){
      this.orderListData = new MyOrderDataSource()
    }
    if (data.data?.content != undefined){
      let list : ShopDeviceOrderListContent[] = data.data.content
      for (let index = 0; index < list.length; index++) {
        let data : ShopDeviceOrderListContent = list[index] as ShopDeviceOrderListContent
        for(let dict of this.paymentMethodDictList){
          if (data.payType == dict.value){
            data.payMethodName = dict.label
          }
        }
        this.orderListData.pushData(data)
      }
      if (list.length < this.query.size){
        //没有更多数据
        this.noMoreShow = true
      } else {
        this.query.nextPage()
      }
    } else {
      let bean : ErrorBean = JSON.parse(JSON.stringify(data.data)) as ErrorBean
      showToast(bean.message!)
    }
    this.loading = false
    this.isRefreshing = false
  })
}
export class MyOrderDataSource extends OrderBasicDataSource {

  private dataArray: ShopDeviceOrderListContent[] = [];

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

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

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

  public pushData(data: ShopDeviceOrderListContent): 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 changeData(index: number): void {
    this.notifyDataChange(index);
  }
}
export class OrderBasicDataSource implements IDataSource {
  private listeners: DataChangeListener[] = [];
  private originDataArray: ShopDeviceOrderListContent[] = [];

  /*constructor(list: CustomBeanType[]) {
    this.originDataArray = list
  }*/

  public totalCount(): number {
    return 0;
  }

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

  public registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      //console.info('add listener');
      this.listeners.push(listener);
    }
  }

  public unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      //console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }

  public notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }

  public notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    })
  }

  public notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
    })
  }

  public notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
    })
  }

  public notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
    })
  }

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

更多关于HarmonyOS鸿蒙Next中使用LazyForEach做分页查询刷新列表,把数据pushData后,出现页面跳到第一条数据的bug,如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

如果你是想要在到onReachEnd的时候就跳回到第一条listitem的话,使用scrollEdge就能做到,使用下面的方法:

private scroller: ListScroller = new ListScroller()
.onReachEnd(() =>{
    if (!this.noMoreShow){
        this.initData()
        this.scroller.scrollEdge(Edge.Top)
    }
})

如果理解的意思有偏差,麻烦提供下ShopDeviceOrderListContent、efRcpClientApi、OrderListItem自定义组件、this.query的定义也要麻烦发下,还有视频现象是不是忘记了上传。

或者提供个更加简单的场景复现demo一起看下呢

更多关于HarmonyOS鸿蒙Next中使用LazyForEach做分页查询刷新列表,把数据pushData后,出现页面跳到第一条数据的bug,如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中使用LazyForEach进行分页查询时,如果遇到数据pushData后页面跳到第一条数据的bug,可能是因为LazyForEach的状态管理问题。LazyForEach在数据源发生变化时会重新渲染列表,导致页面跳回第一条数据。

解决方法可以通过以下步骤实现:

  1. 保持数据源稳定性:确保数据源在pushData时不会触发LazyForEach的重新渲染。可以通过在数据源中添加唯一标识符(如ID)来避免重复渲染。

  2. 使用@State@Link管理数据:通过@State@Link修饰的数据源可以更好地控制列表的渲染行为,避免不必要的刷新。

  3. 手动控制滚动位置:在pushData后,手动设置列表的滚动位置,避免跳回第一条数据。可以通过Scroll组件的scrollTo方法实现。

  4. 优化数据更新逻辑:在pushData时,尽量避免直接修改数据源,而是通过setStateupdate方法来更新数据,从而减少不必要的渲染。

通过这些方法,可以有效解决LazyForEach在分页查询时页面跳回第一条数据的问题。

在HarmonyOS鸿蒙Next中使用LazyForEach进行分页查询刷新列表时,如果出现页面跳到第一条数据的问题,通常是由于数据源更新后,LazyForEach重新渲染导致的。解决方法如下:

  1. 保持数据源不变:在分页查询时,确保新数据是追加到现有数据源中,而不是替换整个数据源。
  2. 使用Key机制:为LazyForEach中的每一项设置唯一Key,确保在数据更新时只重新渲染新增的项,而不是整个列表。
  3. 控制滚动位置:在数据更新后,手动控制列表的滚动位置,避免跳转到第一条数据。

示例代码:

// 假设dataSource是当前数据源,newData是新查询的数据
dataSource.push(...newData);

// 更新列表
listController.scrollToIndex(previousScrollIndex);

通过以上方法,可以有效避免页面跳到第一条数据的问题。

回到顶部