HarmonyOS 鸿蒙Next LazyForEach没有刷新index

发布于 1周前 作者 sinazl 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next LazyForEach没有刷新index

@ComponentV2
export struct ConditionMoreInputComp {
  @Param placeholderText: string = ''
  @Param label: string = ''
  @Local showTxt: string = ''
  @Param keywordsList: KeywordModel[] = []
  @Event addData: (data: KeywordModel) => void
  @Event removeData: (index: number) => void
  dataSource: MutableArrayDataSource<KeywordModel> = new MutableArrayDataSource(this.keywordsList)

  aboutToAppear(): void {
    this.dataSource.pushData(new KeywordModel())
  }

  add() {
    if (this.dataSource.totalCount() >= 5) {
      toast('最多添加 5 组关键词')
      return
    }
    const empty = new KeywordModel()
    this.addData(empty)
    this.dataSource.pushData(empty)
  }

  build() {
    Row() {
      if (this.label) {
        Text(this.label)
          .fontSize(15)
          .margin({ right: 5 })
          .padding({
            top: 12,
            bottom: 12,
          })
          .fontColor(Colors.Color66)
      }
      List({ space: 10 }) {
        LazyForEach(this.dataSource, (item: KeywordModel, index: number) => {
          ListItem() {
            ItemKeyWordComp({
              isFirst: index === 0,
              item: item,
              add: () => {
                this.add()
              },
              remove: () => {
                LogUtil.error('删除的Index' + index)
                this.dataSource.removeData(index)
                this.removeData(index)
              }
            })
          }
          .backgroundColor(Color.White)
        }, (item: KeywordModel, index) => JSONUtil.beanToJsonStr(item) + '-' + index)
      }
      .layoutWeight(1)
    }
    .alignItems(VerticalAlign.Center)
  }
}

@ComponentV2
struct ItemKeyWordComp {
  @Param @Once isFirst: boolean = true
  @Param @Once item: KeywordModel = new KeywordModel()
  @Event add: () => void
  @Event remove: () => void

  build() {
    Row() {
      Row() {
        if (!this.isFirst) {
          Row() {
            Text(this.item.IsContains ? '且包含' : '且不包含',)
              .fontSize(15)
              .fontColor(Colors.ColorAB)
            Image($r('app.media.ic_arrow_down'))
              .fitOriginalSize(true)
              .fillColor(Colors.ColorAB)
          }
          .borderWidth({ right: 0.2 })
          .alignItems(VerticalAlign.Center)
          .padding({
            left: 5,
            right: 5,
          })
          .bindMenu([
            {
              value: '且包含',
              action: () => {
                this.item.IsContains
              }
            },
            {
              value: '且不包含',
              action: () => {
                !this.item.IsContains
              }
            },
          ])
          .height('100%')
        }
        TextInput({ text: this.item.Keyword, placeholder: '请输入关键词' })
          .placeholderColor(Colors.ColorAB)
          .placeholderFont({ size: 15 })
          .maxLines(1)
          .caretColor(Colors.ThemeColor)
          .copyOption(CopyOptions.InApp)
          .type(InputType.Normal)
          .padding({
            left: 5,
            right: 5
          })
          .fontSize(15)
          .fontColor(Colors.Color33)
          .maxLength(50)
          .enterKeyType(EnterKeyType.Next)
          .showPasswordIcon(false)
          .backgroundColor(Color.Transparent)
          .enableKeyboardOnFocus(false)
          .cancelButton({
            style: CancelButtonStyle.INPUT,
            icon: {
              src: $r('app.media.ic_fork'),
              color: Colors.ColorCC,
              size: 14,
            }
          })
          .layoutWeight(1)
          .onChange((value) => {
            this.item.Keyword = value
          })
          .height('100%')
      }
      .alignItems(VerticalAlign.Center)
      .height('100%')
      .layoutWeight(1)
      .borderColor(Colors.ColorAB)
      .borderRadius(3)
      .borderWidth(0.2)

      Text(this.isFirst ? ' + ' : ' - ')
        .width(30)
        .fontSize(15)
        .textAlign(TextAlign.Center)
        .fontColor(Colors.Color33)
        .onClick(() => {
          this.isFirst ? this.add() : this.remove()
        })
        .height('100%')
        .margin({ left: 3 })
        .padding({ top: 12, bottom: 12 })
        .borderColor(Colors.ColorAB)
        .borderRadius(3)
        .borderWidth(0.2)
    }
    .height(40)
    .padding({ right: 1 })
    .width('100%')
    .justifyContent(FlexAlign.Start)
  }
}

从中间开始删除的话,那个Index没有变

export default class BasicDataSource<T> implements IDataSource {
  private listeners: DataChangeListener[] = []
  private mutable: T[]

  constructor(list: T[]) {
    this.mutable = list
  }

  hasMore(totalCount?: number): boolean {
    return this.totalCount() < (totalCount ?? 0)
  }

  getDataList(): T[] {
    return this.mutable
  }

  totalCount(): number {
    return this.mutable.length
  }

  getData(index: number): T {
    return this.mutable[index]
  }

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

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

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

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

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

  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      this.listeners.push(listener)
    }
  }

  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener)
    if (pos >= 0) {
      this.listeners.splice(pos, 1)
    }
  }
}

import BasicDataSource from './base/BasicDataSource'

export default class MutableArrayDataSource<T> extends BasicDataSource<T> {
  private dataList: T[]

  constructor(list: T[] = []) {
    super(list)
    this.dataList = list
  }

  public getDataList(): T[] {
    return this.dataList
  }

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

  public getData(index: number): T {
    return this.dataList[index]
  }

  public addData(index: number, data: T) {
    this.dataList.splice(index, 0, data)
    this.notifyDataAdd(index)
  }

  public pushDataList(dataList: T[]) {
    dataList.forEach((item) => {
      this.dataList.push(item)
      this.notifyDataAdd(this.dataList.length - 1)
    })
  }

  public pushData(data: T) {
    this.dataList.push(data)
    this.notifyDataAdd(this.dataList.length - 1)
  }

  public removeData(index: number) {
    this.dataList.splice(index, 1)
    this.notifyDataDelete(index)
  }

  public clear() {
    this.dataList = []
    this.notifyDataReload()
  }
}

更多关于HarmonyOS 鸿蒙Next LazyForEach没有刷新index的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

在删除一个数据项后调用reloadData方法,重建后面的数据项,以达到更新index索引的目的

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

  public totalCount(): number {
    return 0;
  }

  public getData(index: number): string {
    return this.originDataArray[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);
    }
  }

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

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

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

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

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

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

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

@Entry
@Component
struct MyComponent {
  private data: MyDataSource = new MyDataSource();

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

  build() {
    List({ space: 3 }) {
      LazyForEach(this.data, (item: string, index: number) => {
        ListItem() {
          Row() {
            Text(item).fontSize(50)
              .onAppear(() => {
                console.info("appear:" + item,index)
              })
          }.margin({ left: 10, right: 10 })
        }
        .onClick(() => {
          // 点击删除子组件
          this.data.deleteData(index);
          // 重置所有子组件的index索引
          this.data.reloadData();
        })
      }, (item: string, index: number) => item + index.toString())
    }.cachedCount(5)
  }
}

更多关于HarmonyOS 鸿蒙Next LazyForEach没有刷新index的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


JSONUtil.beanToJsonStr(item) ,我看了一下,KeywordModel在代码里只两个值,并且,添加的时候直接new,没有做数据处理,那么,jsonStr都是一样的吧?这样LazyForEach的add时候因为index 所以,是唯一的。但是remove的时候。key值没变化(只是总数少了一个)。应该渲染异常了

在HarmonyOS(鸿蒙)中,LazyForEach 组件的 index 未刷新的问题通常与数据绑定或组件内部状态管理有关。LazyForEach 用于高效地渲染列表项,但如果数据源或组件状态未正确更新,index 可能不会按预期刷新。

要解决这个问题,请检查以下几点:

  1. 数据源更新:确保在修改列表数据后,触发数据源的更新。如果数据源是一个可变集合,确保使用适当的方法来修改集合,例如使用 addremove 等方法,并通知UI层更新。

  2. 组件状态管理:检查 LazyForEach 组件及其子组件的状态管理。如果子组件依赖于外部状态(如全局状态或父组件的状态),确保这些状态在数据变化时得到正确更新。

  3. 重新渲染:在数据变化后,确保 LazyForEach 能够感知到数据变化并重新渲染。这通常依赖于数据绑定框架的自动更新机制。

  4. 组件内部逻辑:检查 LazyForEach 组件及其子组件的内部逻辑,确保没有逻辑错误导致 index 更新失败。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!