HarmonyOS 鸿蒙Next List组件 利用LazyForEach 后不能用scroller.scrollto 去跳转

发布于 1周前 作者 phonegap100 来自 鸿蒙OS

HarmonyOS 鸿蒙Next List组件 利用LazyForEach 后不能用scroller.scrollto 去跳转 我需要加载一个长列表,然后需要跳转到指定的一个子控件的位置,之前用ForEach, 然后scroller.scrollto 指定位置,是可以的,但是考虑到性能优化,就改用LazyForEach,之后scroller.scrollto不能用了,有没有类似iosUItableView 的api或者控件,保证懒加载的同时还能支持跳转相应位置?

2 回复

使用 LazyForEach 时,scrollTo 是生效的,

// Basic implementation of IDataSource to handle data listener

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);
    })
  }

  // 通知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);
    })
  }
}

class MyDataSource extends BasicDataSource {

  private dataArray: string[] = [];

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

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

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

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

@Entry
@Component
struct MyComponent {

  private data: MyDataSource = new MyDataSource();

  private scroller: ListScroller = new ListScroller();

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

  build() {
    Column() {
      List({ space: 3, initialIndex: 4, scroller: this.scroller }) {
        LazyForEach(this.data, (item: string) => {
          ListItem() {
            Row() {
              Text(item).fontSize(50)
                .onAppear(() => {
                  console.info("appear:" + item)
                })
            }.margin({ left: 10, right: 10 })
          }
        }, (item: string) => item)
      }.cachedCount(5).height('70%')

      Divider().padding(8)

      Button('scroll to').onClick(() => {
        this.scroller.scrollTo({xOffset: 0, yOffset: 310})
      })
    }
  }
}

当数据源的数组项为对象数据类型,并且只修改某个数组项的属性值时,由于数据源为复杂数据类型,ArkUI框架无法监听到@State装饰器修饰的数据源数组项的属性变化,从而无法触发ForEach的重新渲染。

要实现ForEach重新渲染,需要结合@Observed@ObjectLink装饰器使用

可以先看下:链接

更多关于HarmonyOS 鸿蒙Next List组件 利用LazyForEach 后不能用scroller.scrollto 去跳转的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙系统中,当使用Next List组件并结合LazyForEach进行列表渲染时,如果遇到无法使用scroller.scrollTo进行跳转的问题,这通常是由于LazyForEach的异步加载特性导致的。LazyForEach是为了优化性能而设计的,它按需加载列表项,这可能导致在尝试滚动到某个位置时,该位置的项目还未被实际加载和渲染到DOM中。

要解决这个问题,你可以尝试以下方法:

  1. 确保元素已加载:在调用scroller.scrollTo之前,确保要跳转到的元素已经加载完成。这可能需要通过某种方式监听LazyForEach的加载状态。

  2. 使用定时器延迟调用:虽然这不是最佳实践,但在某些情况下,使用定时器(如setTimeout)短暂延迟scrollTo的调用,可以等待LazyForEach完成部分加载。

  3. 手动触发重绘:尝试在调用scrollTo之前,通过某种方式触发页面的重绘,以确保所有元素都已渲染。

请注意,这些方法可能需要根据具体的实现细节进行调整。如果问题依旧没法解决请联系官网客服,官网地址是 https://www.itying.com/category-93-b0.html

回到顶部