HarmonyOS 鸿蒙Next 关于harmony列表刷新问题

HarmonyOS 鸿蒙Next 关于harmony列表刷新问题 有一个商品列表,使用grid展示,实体类用@Observed修饰,代码片段是:

const tag = 'VipPages'

@Page({ name: 'vipPages' })
@Entry
@Component
struct VipPages {
  @State userInfoBean: UserInfoBean = authStore.getUser()
  @State goodBeans: GoodBean[] = []
  loginViewModel: LoginViewModel = LoginViewModel.getInstance()

  onPageShow(): void {
    immersionBar.immersion({ transparentStatusBar: true })
  }

  loadingdialog: CustomDialogController = new CustomDialogController({
    builder: HdLoadingDialog({ message: '正在加载中...' }),
    customStyle: true,
    alignment: DialogAlignment.Center
  })

  aboutToAppear(): void {
    this.loadingdialog?.open()
    this.loginViewModel.getVipGoodList().then(res => {
      if (res.list) {
        this.loadingdialog?.close()
        logger.debug(tag, '获取商品信息成功1-->' + res.list.length)
        for (let i = 0; i < res.list.length; i++) {
          if (i == 0) {
            res.list[i].isSelect = true
          } else {
            res.list[i].isSelect = false
          }
          this.goodBeans.push(res.list[i])
        }
      }
    }).catch(error => {
      this.loadingdialog?.close()
    })
  }

  build() {
    Scroll() {
      Column() {
        Stack() {
          Image($r('app.media.ic_vip_bg')).width(CommonConstants.FULL_PERCENT).objectFit(ImageFit.Contain)
          Column() {
            headTitle({
              title: '会员中心', handleClick: () => {
                router.back()
              }, barTop: 0
            })
            Stack() {
              Image($r('app.media.ic_vip_user_bg')).width(CommonConstants.FULL_PERCENT).objectFit(ImageFit.Contain)
              Row() {
                Image(this.userInfoBean != null ? this.userInfoBean.headImgUrl : $r('app.media.ic_me_user'))
                  .alt($r('app.media.ic_me_user'))
                  .objectFit(ImageFit.Fill)
                  .width('42vp')
                  .height('42vp')
                  .borderRadius('100vp')
                Column() {
                  Text(UserInfoUtils.userNameFilfter(this.userInfoBean != null ? this.userInfoBean : null))
                    .fontColor('#815120')
                    .fontSize('16fp')
                    .fontWeight(FontWeight.Bold)
                  Text(UserInfoUtils.userLevel(this.userInfoBean != null ? this.userInfoBean : null))
                    .fontColor('#97724D')
                    .fontSize('12fp')
                    .margin({ top: '8vp' })
                }.size({ width: CommonConstants.FULL_PERCENT }).alignItems(HorizontalAlign.Start).margin({ left: 12 })
              }.width(CommonConstants.FULL_PERCENT).margin({ left: 20, top: 30 }).alignItems(VerticalAlign.Center)
            }.padding({ left: 20, right: 20 }).width(CommonConstants.FULL_PERCENT)
          }.width(CommonConstants.FULL_PERCENT)

        }.width(CommonConstants.FULL_PERCENT)

        Row() {
          Text() {
            ImageSpan($r('app.media.ic_item_note')).width(10).height(10).verticalAlign(ImageSpanAlignment.CENTER)
            Span('未成年人须在监护人陪同下购买,购买前请仔细阅读购买须知').margin({ left: 8 })
          }
          .width(CommonConstants.FULL_PERCENT)
          .backgroundColor('#FFEDEC')
          .fontSize('11fp')
          .fontColor('FE4F45')
          .padding({ top: 13, left: 12, bottom: 12 })
          .borderRadius(8)

        }.width(CommonConstants.FULL_PERCENT).margin({ top: 16 }).padding({ left: 16, right: 16 })

        //商品信息
        Grid() {
          ForEach(this.goodBeans, (item: GoodBean, index: number) {
            GridItem() {
              ViPItem({
                goodBean: item
              , positon: index
              , handleClick: (goodBean: GoodBean) => {
                  for (let i = 0; i < this.goodBeans.length; i++) {
                    if (goodBean.id != this.goodBeans[i].id) {
                      this.goodBeans[i].isSelect = false
                    }
                  }
                }
              })
            }
          }, (item: GoodBean) => item.id)
        }
        .scrollBar(BarState.Off)
        .rowsTemplate(('1fr 1fr 1fr') as string)
        .columnsTemplate(('1fr 1fr 1fr') as string)
        .columnsGap(3)
        .margin({ top: 13 })
        .width(CommonConstants.FULL_PERCENT)

      }.height(CommonConstants.FULL_PERCENT)
      .width(CommonConstants.FULL_PERCENT)
      .alignItems(HorizontalAlign.Start)
      .justifyContent(FlexAlign.Start)
    }.width(CommonConstants.FULL_PERCENT).height(CommonConstants.FULL_PERCENT)
    .backgroundColor(Color.White)
  }
}

@Component
struct ViPItem {
  @ObjectLink goodBean: GoodBean;
  @Prop positon: number;
  handleClick: (goodBean: GoodBean) => void =
    (goodBean: GoodBean) => {}

  build() {
    RelativeContainer() {
      Column() {
        Text(this.goodBean.name)
          .fontColor(this.goodBean.isSelect ? '#E9A557' : '#333333')
          .fontSize(14)
          .margin({ top: 14 })
        Row() {
          Text('¥').fontColor(this.goodBean.isSelect ? '#E9A557' : '#333333').fontSize(12).fontWeight(FontWeight.Bold)
          Text(ParamsUtils.getPrice(this.goodBean.price))
            .fontColor(this.goodBean.isSelect ? '#E9A557' : '#333333')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)

        }.alignItems(VerticalAlign.Center).margin({ top: 6 })

        Text(`原价:${ParamsUtils.getPrice(this.goodBean.originalPrice)}`)
          .fontColor('#999999')
          .fontSize(11)
          .decoration({
            type: TextDecorationType.LineThrough,
            color: '#999999'
          })
          .padding(10)
          .margin(5)
          .margin({ top: 2 })
        Text(`${this.goodBean.heavenPrice}元/天`).fontColor('#333333').fontSize(10).fontWeight(FontWeight.Bold)
          .margin({ top: 5, bottom: 10 })
      }
      .width(CommonConstants.FULL_PERCENT)
      .id('cl1')
      .alignRules({
        top: { anchor: 'tv1', align: VerticalAlign.Top }
      })
      .alignItems(HorizontalAlign.Center)
      .margin({ top: 10 })
      .border({ radius: 10, width: 2, color: this.goodBean.isSelect ? '#E9A557' : '#DDDDDD' })

      Text('特享优惠')
        .fontSize(10)
        .padding({
          left: 7,
          top: 3,
          bottom: 3,
          right: 5
        })
        .fontColor(Color.White)
        .linearGradient({
          direction: GradientDirection.Right, // 渐变方向
          repeating: false, // 渐变颜色是否重复
          colors: [[0xffff7871, 0.1], [0xfffe4c42, 1.0]]
        })
        .borderRadius(5)
        .id('tv1')
        .visibility(this.positon == 0 ? Visibility.Visible : Visibility.Hidden)
    }.width(CommonConstants.FULL_PERCENT).backgroundColor(Color.White).padding({ left: 7, right: 7 })
    .onClick(() => {
      this.goodBean.isSelect = !this.goodBean.isSelect
      this.handleClick(this.goodBean)
    })
  }
}
实体类片段
[@Observed](/user/Observed)
export class GoodBean {
  isSelect: boolean = false; //是否选中
}

当点击列表,改变isSelect值时,列表不刷新


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

3 回复

我按照你的代码逻辑写了个Demo,但是好像是可以修改list数据的

@Entry
@Component
struct ComponentsPage {
  @State infos: TestBean[] = []

  aboutToAppear(): void {
    this.infos.push(
      new TestBean(true, '1'),
      new TestBean(false, '2'),
      new TestBean(false, '3'),
      new TestBean(false, '4'),
      new TestBean(false, '5'),
      new TestBean(false, '6'),
      new TestBean(false, '7')
    )
  }

  build() {
    Column() {
      ForEach(this.infos, (item: TestBean) => {
        ChildCom({
          child: item, 
          handleClick: (item: TestBean) => {
            this.infos.forEach((item1: TestBean) => {
              if (item1.name != item.name) {
                item1.isSelected = false
              } else {
                item1.isSelected = true
              }
            })
          }
        })
      })
    }
    .height('100%')
    .width('100%')
  }
}

@Component
export struct ChildCom {
  @ObjectLink child: TestBean
  handleClick: (child: TestBean) => void = (child: TestBean) => {}

  build() {
    Column() {
      Radio({ value: this.child.name, group: 'radioGroup' })
        .checked(this.child.isSelected)
        .radioStyle({
          checkedBackgroundColor: Color.Pink
        })
        .height(50)
        .width(50)
        .onClick(() => {
          this.handleClick(this.child)
        })
    }
  }
}

@Observed
export class TestBean {
  isSelected: boolean = false;
  name: string = ''

  constructor(isSelected: boolean, name: string) {
    this.isSelected = isSelected
    this.name = name
  }
}

没看出来写法上的问题,你这边说的List未刷新的现象是什么?

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


可以把VIPItem移到父组件上

针对HarmonyOS 鸿蒙Next中的harmony列表刷新问题,这里提供直接的技术解答:

在HarmonyOS中,若遇到列表刷新问题,首先需确认列表数据源是否已正确更新。HarmonyOS提供了丰富的UI组件库,其中列表组件通常与数据绑定机制相关联。当数据源发生变化时,列表应自动刷新以反映最新数据。

若列表未自动刷新,可检查以下几点:

  1. 数据绑定:确保列表组件已正确绑定到数据源。在数据模型更新后,绑定机制应触发列表的重新渲染。

  2. 状态管理:如使用状态管理机制(如MVVM、Flux等),需确保状态更新已正确触发并传播到列表组件。

  3. UI线程:UI更新应在主线程(UI线程)中进行。若从后台线程更新UI,需使用适当的线程切换机制。

  4. 列表组件属性:检查列表组件的相关属性设置,如itemCountitemBuilder等,确保它们正确无误且响应数据变化。

  5. 调试与日志:使用HarmonyOS提供的调试工具查看列表组件的状态和数据绑定情况,检查是否有异常日志输出。

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

回到顶部