HarmonyOS 更新数据后UI不刷新

@Entry
@Component
struct NavRootPage {
  @State rootData: RootData = new RootData()

  aboutToAppear(): void {
    this.rootData.textData = new TextData()
    this.rootData.textData.text = "1"
  }

  build() {
    Column() {

      CellRoot({ cellData: this.rootData })

      Button('change').onClick(() => {
        setTimeout(() => {
          for (let i = 0; i < 20; i++) {
            this.rootData.textData!.text = `${i}`
          }
        })
      })
    }
    .height('100%')
    .width('100%')
  }
}

@Builder
function TextCellBuilder() {
  TextCell()
}

@Observed
class RootData {
  builder: WrappedBuilder<[]> = wrapBuilder(TextCellBuilder)
  textData?: TextData
}

@Observed
class TextData {
  text?: string | Resource
}

@Component
struct CellRoot {
  @Provide cellData: RootData = new RootData()

  build() {
    this.cellData.builder.builder()
  }
}

@Component
struct TextCell {
  @Consume cellData: RootData

  build() {
    Column() {
      if (this.cellData.textData) {
        TextDemo({ data: this.cellData.textData })
      }
    }
  }
}

@Component
struct TextDemo {
  @ObjectLink data: TextData

  build() {
    Text(this.data.text)
  }
}

component和数据包含关系:CellRoot(provide cellData) -> TextCell(consume cellData) -> TextDemo(objectLink data from cellData)

CellRoot应用在列表上,为可复用组件

在ViewModel中创建数据

rootData = new RootData()
rootData.textData = new TextData()
rootData.textData.text = "1"

在处理了一些逻辑之后,手动设置

rootData.textData.text = "2"

UI偶现不刷新,尤其是频繁触发列表刷新的时候

HarmonyOS
1天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
FengTianYa

请尝试在 @Reusable 组件中,重新赋值上层组件传递的数据

aboutToReuse(params: Record<string, RootData>): void {
  this.cellData = params.cellData; // 重新赋值
}

可参考如下demo:

本demo在provide、consume、objectLink层级修改数据UI层都可以正常刷新

let uid = 1;

export class MyDataSource<T = string> implements IDataSource {
  private list: T[] = [];

  constructor(list?: T[]) {
    if (list) {
      this.list = list;
    }
  }

  public pushData(data: T): void {
    this.list.push(data);
  }

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

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

  registerDataChangeListener(): void {
  }

  unregisterDataChangeListener(): void {
  }
}

@Observed
class RootData {
  builder: WrappedBuilder<[]> = wrapBuilder(TextCellBuilder)
  textData?: TextData
}

@Observed
class TextData {
  text?: string | Resource;
  spanDataArray?: BaseData[]
}

@Observed
class BaseData {
  text?: string | Resource;

  constructor(text: string) {
    this.text = text;
  }
}

@Entry
@Component
struct Index {
  @State rootData: RootData = new RootData()
  @State list: MyDataSource<RootData> = new MyDataSource();

  aboutToAppear(): void {
    this.rootData.textData = new TextData()
    this.rootData.textData.text = "1";


    for (let i = 0; i <= 20; i++) {
      const rootData = new RootData();
      rootData.textData = new TextData();
      rootData.textData.text = `T${i}`;
      rootData.textData.spanDataArray = [new BaseData(`S${i}`)];
      this.list.pushData(rootData); // 0-20
    }
  }

  build() {
    Column() {
      Scroll() {
        Column() {
          CellRoot({ cellData: this.rootData });
          Button('change').onClick(() => {
            setTimeout(() => {
              for (let i = 0; i < 20; i++) {
                uid++;
                this.rootData.textData!.text = `T${uid}`;
              }
              this.rootData.textData!.spanDataArray = [new BaseData(`${uid}`)];
            })
          })

          List() {
            LazyForEach(this.list, (item: RootData) => {
              ListItem() {
                CellRoot({ cellData: item })
              }
              .width('100%')
              .height(100)
            }, (item: RootData) => JSON.stringify(item))
          }.cachedCount(5)
        }
      }

    }
    .height('100%')
    .width('100%')
  }
}


@Reusable
@Component
struct CellRoot {
  @Provide cellData: RootData = new RootData()

  aboutToReuse(params: Record<string, RootData>): void {
    console.log('aboutToReuse', this.getUniqueId())
    this.cellData = params.cellData; // 重新赋值
  }

  build() {
    Column() {
      Text(`Provide:${this.cellData.textData?.text}`)
        .onClick(() => {
          changeUid(this.cellData.textData as TextData);
        })
      this.cellData.builder.builder()
    }
  }
}

@Builder
function TextCellBuilder() {
  TextCell()
}

@Component
struct TextCell {
  @Consume cellData: RootData

  build() {
    Column() {
      Text(`Consume:${this.cellData.textData?.text}`)
        .onClick(() => {
          changeUid(this.cellData.textData as TextData);
        })
      TextDemo({ data: this.cellData.textData });
    }
  }
}

@Component
struct TextDemo {
  @ObjectLink data: TextData

  build() {
    Column() {
      Text(`Text:${this.data.text}`)
        .onClick(() => {
          changeUid(this.data);
        });
      ForEach(this.data.spanDataArray, (item: BaseData) => {
        Text(`spanText:${item.text}`)
      })
    }
  }
}

function changeUid(data: TextData) {
  uid++;
  console.log(`uid:${uid}`)
  const t = `${uid}`;
  data.text = t;
  data.spanDataArray = [new BaseData(t)];
}
分享
微博
QQ
微信
回复
1天前
相关问题
IF条件变化UI刷新
882浏览 • 1回复 待解决
HarmonyOS UI未在数据更新刷新
22浏览 • 1回复 待解决
HarmonyOS UI刷新
215浏览 • 1回复 待解决
修改ForEach使用的数据对象,UI刷新
2085浏览 • 1回复 待解决
HarmonyOS 卡片更新图片刷新
163浏览 • 1回复 待解决
HarmonyOS UI刷新问题
170浏览 • 1回复 待解决
HarmonyOS LIst组件UI刷新
21浏览 • 1回复 待解决
HarmonyOS @builder方法的ui刷新
250浏览 • 1回复 待解决
HarmonyOS使用@ObjectLink 数据刷新
936浏览 • 2回复 待解决
状态装饰器 ui刷新的问题
2560浏览 • 1回复 待解决
HarmonyOS UI和ViewModel如何刷新数据
33浏览 • 1回复 待解决
HarmonyOS 深色模式切换界面刷新
180浏览 • 1回复 待解决
HarmonyOS 懒加载列表更改属性UI刷新
179浏览 • 1回复 待解决