HarmonyOS鸿蒙Next中数据变化了,但是视图没有更新

HarmonyOS鸿蒙Next中数据变化了,但是视图没有更新 在一个对象中我定义了字段。在使用eventHub的情况下,能确定数据是接收到了,可是页面没重新渲染,没有替换成最新选中的数据。

其中有个现象是这样的。 如果当前的对象没有赋值(类似页面第一次编辑是没数据的,如果提交过了,我会请求接口拿到上次编辑的数据、然后赋值到对象中)是可以正常渲染的, 如果有赋值的情况下就不行(页面第二次渲染展示的还是第一次的值)。

cke_3487.png


更多关于HarmonyOS鸿蒙Next中数据变化了,但是视图没有更新的实战教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

开发者您好,请确认下是不是通过JSON.parse反序列化的方式创建的CiticInfoBean对象?通过这种方式创建的对象使用@ObservedV2与@Trace装饰器是监听不到变化的,可以参考使用限制最后一条。可以通过如下代码复现问题,需要通过new操作符实例化对象,这样实例化的对象才具备被观测变化的能力

@ObservedV2
class CiticInfoBean{
  @Trace branchName:string = 'hello'
}

@ObservedV2
class CustomBean{
  @Trace mInfoBean: CiticInfoBean = new CiticInfoBean()
}
@Entry
@ComponentV2
struct Index {
  
  uiContext = this.getUIContext();
  context = this.uiContext?.getHostContext()

  @Local CiticInfoJson: CiticInfoBean = new CiticInfoBean()
  @Local CiticInfo: CiticInfoBean = new CiticInfoBean()

  aboutToAppear(): void {
    let json = '{"branchName":"hello"}'
    this.CiticInfoJson = JSON.parse(json) as CiticInfoBean
    if (this.context!=null) {
      this.context.eventHub.on('myEvent', (data:string)=>{
        //this.custom.mInfoBean.branchName = data
        this.CiticInfo.branchName = data
        this.CiticInfoJson.branchName = data
      });
    }
  }

  @Local count:number = 0
  build() {
    Column() {
      Text('反序列化创建对象'+this.CiticInfoJson.branchName)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
      Text('通过new创建对象'+this.CiticInfo.branchName)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
      Button('改变对象')
        .onClick(()=>{
          if (this.context!=null) {
            this.context.eventHub.emit('myEvent','hello'+this.count++);
          }
        })
    }
    .height('100%')
    .width('100%')
  }
}

更多关于HarmonyOS鸿蒙Next中数据变化了,但是视图没有更新的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


【问题背景】

  • 状态管理V2装饰器会为装饰的变量生成getter和setter方法,同时为原有变量名添加__ob_的前缀,当前无法避免,详情请参考官方文档:获取状态管理V2代理前的原始对象。@ObservedV2的类实例目前不支持使用JSON.stringify进行序列化,详情请参考使用限制
"dateTimeGroup": {
  "__ob_beginDate": "2024-06-05",
  "__ob_beginTime": "17:00",
  "__ob_endDate": "2024-06-07",
  "__ob_endTime": "17:00"
}

【解决方案】

  • 状态管理框架已提供[@ObservedV2/@Trace](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-observedv2-and-trace)用于观察类属性变化,makeObserved接口提供主要应用于@ObservedV2/@Trace无法涵盖的场景:
    • class的定义在三方包中:开发者无法手动对class中需要观察的属性加上@Trace标签,可以使用makeObserved使得当前对象可以被观察。
    • 当前类的成员属性不能被修改:因为@Trace观察类属性会动态修改类的属性,这个行为在@Sendable装饰的class中是不被允许的,此时可以使用makeObserved。
    • interface或者JSON.parse返回的匿名对象:这类场景往往没有明确的class声明,开发者无法使用@Trace标记当前属性可以被观察,此时可以使用makeObserved。

试试这个:

makeObserved接口:将非观察数据变为可观察数据-其他状态管理-状态管理(V2)-学习UI范式状态管理-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

我在检查代码的时候发现问题了,是这里的数据保存的情况下造成的。

这种数据的保存会序列化,可是我的数据值是有做监听的。@Trace 使用了这个。第一次赋值的情况下是正常,在第二次修改这个值就无法重新渲染页面。

图片

在HarmonyOS Next中,视图未随数据更新通常由以下原因导致:

  1. 未使用@State@Observed装饰器标记数据变量,导致ArkUI框架无法监测数据变更。

  2. 在自定义组件中修改未用@Prop@Link接收的参数,这类修改不会触发父组件重新渲染。

  3. 直接修改数组元素或对象属性而非整个引用,建议使用展开运算符创建新对象。

  4. 在非UI线程修改状态数据,需确保数据变更在主线程执行。

  5. 使用了不支持的变量类型或修改方式,应使用框架推荐的响应式数据类型和更新方法。

在HarmonyOS Next中,数据变化但视图未更新的问题通常与状态管理机制有关。从描述来看,首次渲染正常而后续更新失效,可能是以下原因导致:

  1. 状态对象未正确触发响应式更新
    HarmonyOS的ArkUI框架依赖状态变量(如@State)驱动UI刷新。如果数据对象未用响应式装饰器声明,或直接修改了对象引用而非属性,框架无法检测变更。
    解决方案

    • 确保数据对象使用@State装饰器声明
    • 修改对象时通过解构或Object.assign()创建新引用,例如:
      this.data = { ...this.data, key: newValue }; // 触发更新
      
  2. EventHub事件处理中未正确更新状态
    即使接收到事件数据,若直接修改现有对象的属性(如this.data.field = value),可能绕过响应式系统。
    建议操作

    • 在事件回调中重新赋值整个对象,或使用@Watch监听变化
  3. 嵌套数据更新的特殊性
    如果对象包含深层嵌套结构,需对具体修改的层级使用@State,或考虑使用@Observed@ObjectLink实现局部刷新。

可检查代码中是否满足以下条件:

  • 数据源被@State/@Provide等装饰器包装
  • 修改数据时遵循不可变原则(生成新对象)
  • 事件回调中调用this.data = newData而非仅修改属性

通过调整状态更新方式,通常可解决视图同步问题。

回到顶部