HarmonyOS 鸿蒙Next状态管理中this的问题

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

HarmonyOS 鸿蒙Next状态管理中this的问题

@Entry
@Component
struct PlayDetailPage {
@State vm: PlayDetailViewModel = new PlayDetailViewModel();

build() { Stack() { Text(this.vm.coverUrl).width(100).height(100).backgroundColor(this.vm.coverUrl) Row() { Button(‘点击改变颜色’) .onClick(() => { // ------- 这样写是 ok 的 let self = this.vm; this.vm.changeCoverUrl(self);

        <span class="hljs-comment"><span class="hljs-comment">// ------- 这样写是不行的</span></span>
        <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.vm.changeCoverUrl(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.vm);
      })
  }
}
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.height(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.alignContent(Alignment.Top)

} }

export default class PlayDetailViewModel { coverUrl: string = ‘#00ff00’

changeCoverUrl= (model:PlayDetailViewModel)=> { model.coverUrl = ‘#00F5FF’ }

} <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

这是State中的demo,修改了一下,把 let self = this.vm 去掉了 self定义,发现就不能改变颜色了。这在kotlin里感觉是非常常见的写法,为什么ArkTS不行,有没有人可以给解释一下原理

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-state-V5#常见问题

3 回复

我觉得从编译角度更好理解一点

1. 使用[@State](/user/State) 标记的对象变更之所以能刷新UI,是因为编译的时候会在这个对象外包一层proxy。这一点你在断点的时候就能发现this.vm是一个proxy。有Handler和Target。事实上只有通过这个proxy对this.vm进行操作才会触发变更

2. 

// ------- 这样写是 ok 的
let self = this.vm;
this.vm.changeCoverUrl(self);

// ------- 这样写是不行的 this.vm.changeCoverUrl(this.vm);<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

这两个的区别就是第一个this.vm.changeCoverUrl(self);这个self就是proxy。第二个this.vm.changeCoverUrl(this.vm);实际上传递的不是proxy,传递的是proxy中的原始对象。编译的时候会修改成

this.vm.changeCoverUrl(ObservedObject.GetRawObject(this.vm));所以值是变了,但是无法触发UI刷新

编译的产物在build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages下能找到

非常感谢,我理解下

HarmonyOS 鸿蒙Next状态管理中关于this的问题,主要涉及到在ArkTS中如何正确引用组件的状态变量。由于ArkTS使用代理机制来观察状态变化,直接通过this访问的可能是原始对象而非代理对象,这可能导致UI更新不触发。正确的做法是通过代理对象进行操作,确保状态变更能被系统捕捉并触发UI刷新。如果问题依旧没法解决,请加我微信,我的微信是itying888。

回到顶部