HarmonyOS鸿蒙Next中请假使用@ObservedV2+@Trace更新数据UI不更新的问题
HarmonyOS鸿蒙Next中请假使用@ObservedV2+@Trace更新数据UI不更新的问题
[@ObservedV2](/user/ObservedV2)
class TestModel {
[@Trace](/user/Trace) name: string = ''
}
@Entry
@ComponentV2
struct TestPage {
@Local list: Array<TestModel> = []
@Local currentItem: TestModel = new TestModel()
aboutToAppear(): void {
this.list = [{ name: '0' }, { name: '1' }] // 模拟从服务器拿到数据
this.currentItem = this.list[1]
}
build() {
Column({ space: 20 }) {
Text(this.currentItem.name)
Button('change current name')
.onClick(() => {
this.currentItem.name = Math.random().toString()
})
}
.height('100%')
.width('100%')
}
}
点击按钮后,数据变了,但是UI不刷新,求解决办法
更多关于HarmonyOS鸿蒙Next中请假使用@ObservedV2+@Trace更新数据UI不更新的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
背景知识:
楼主使用 this.list = [{ name: ‘0’ }, { name: ‘1’ }] 字面量构造对象导致了 @ObservedV2 和 @Trace 的缺失,无法进行更新ui了。如要更新ui需要将 @ObservedV2 和 @Trace 进行保留。可以使用new方式来进行创建对象。可以参考如下代码
问题处理:
代码实例:
import { AppStorageV2 } from '@kit.ArkUI';
[@ObservedV2](/user/ObservedV2)
class TestModel {
[@Trace](/user/Trace) name: string = ''
constructor(name?: string) {
if(name){
this.name = name;
}
}
}
@Entry
@ComponentV2
struct AppStorageV2Page {
pageStack: NavPathStack = new NavPathStack()
@Local list: Array<TestModel> = []
@Local currentItem: TestModel = new TestModel("0")
aboutToAppear(): void {
this.list = [new TestModel("0"), new TestModel("1")] // 模拟从服务器拿到数据
this.currentItem = this.list[1]
}
build() {
Navigation(this.pageStack) {
Column() {
Text("显示:" + this.currentItem.name)
.fontSize(20)
.fontColor(Color.Black)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
Button("点击修改")
.fontSize(20)
.fontColor(Color.White)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.currentItem.name = Math.random().toString()
console.log("AppStorageV2Page-> " + this.currentItem.name)
})
}
}
}
}
真机演示:
更多关于HarmonyOS鸿蒙Next中请假使用@ObservedV2+@Trace更新数据UI不更新的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
通过{name: ‘0’}创建的对象未被@ObservedV2代理,导致属性变更无法触发UI刷新;@Local装饰器适用于组件内部状态管理,但无法自动触发跨对象层级的响应式更新;直接修改嵌套对象的属性不会触发ArkUI的更新机制,需要显式通知系统
修整后代码:
[@ObservedV2](/user/ObservedV2)
class TestModel {
@Trace name: string = ''
}
@Entry
@ComponentV2
struct TestPage {
[@Local](/user/Local) list: TestModel[] = [];
[@Local](/user/Local) currentItem: TestModel = new TestModel();
aboutToAppear(): void {
const item0 = new TestModel();
item0.name = '0';
const item1 = new TestModel();
item1.name = '1';
this.list = [item0, item1];
this.currentItem = item1;
}
build() {
Column({ space: 20 }) {
Text(this.currentItem.name)
Button('change current name')
.onClick(() => {
const newItem = new TestModel();
newItem.name = Math.random().toString();
this.currentItem = newItem;
})
}
.height('100%')
.width('100%')
}
}
@ObservedV2生效条件:必须通过new创建类实例,字面量对象无法被代理
以下是优化后的代码,测试结果正常
@Entry
@ComponentV2
struct TestPage {
@Local list: Array<TestModel> = []
@Local currentItem: TestModel = new TestModel()
aboutToAppear(): void {
const model0 = new TestModel()
model0.name = "0"
const model1 = new TestModel()
model1.name = "1"
this.list = [model0, model1] // 模拟从服务器拿到数据
this.currentItem = this.list[1]
}
build() {
Column({ space: 20 }) {
Text(this.currentItem.name)
Button('change current name')
.onClick(() => {
this.currentItem.name = Math.random().toString()
})
}
.height('100%')
.width('100%')
}
}
【背景知识】
[@ObservedV2装饰器和@Trace装饰器](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-observedv2-and-trace):@ObservedV2和@Trace提供了对嵌套类对象属性变化直接观测的能力,是状态管理V2中相对核心的能力之一。
【参考方案】
可参考未读消息清除示例,通过[@ObservedV2和@Trace](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-observedv2-and-trace)实现两种方式清除未读消息效果。
利用[@ObservedV2和@Trace](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-observedv2-and-trace)实现对未读消息的类属性变化进行监测,当改变未读消息类属性时会通知相关组件刷新。
// 定义消息类
[@ObservedV2](/user/ObservedV2)
export class MessageInfo {
[@Trace](/user/Trace) picture?: Resource;
...
}
[@ObservedV2](/user/ObservedV2)
export class MessageInfoModel {
// 初始化对象数组
[@Trace](/user/Trace) messageList: MessageInfo[] = [
...
]
// 一键清除改变消息类属性
public updateMessage() {
for (let i = 0; i < this.messageList.length; i++) {
this.messageList[i].numbers = 0
}
}
// 通过索引值清除改变对应消息类属性
public cleanSingleMessage(index: number){
this.messageList[index].numbers = 0
}
// 拿到对象类
private static _instance: MessageInfoModel;
public static get instance() {
if (!MessageInfoModel._instance) {
MessageInfoModel._instance = new MessageInfoModel();
}
return MessageInfoModel._instance;
}
}
debug就可以发现你的代码this.currentItem = this.list[1] 执行完,this.currentItem是object类型,所以监听不到,改成这个看看
@ObservedV2
class TestModel {
@Trace name: string = ''
}
@Entry
@ComponentV2
struct TestPage {
@Local list: Array<TestModel> = []
@Local currentItem: TestModel = new TestModel()
aboutToAppear(): void {
let a : TestModel = new TestModel()
a.name = '0'
let b : TestModel = new TestModel()
b.name = '1'
this.list = [a, b] // 模拟从服务器拿到数据
this.currentItem = this.list[1]
}
build() {
Column({ space: 20 }) {
Text(this.currentItem.name)
Button('change current name')
.onClick(() => {
this.currentItem.name = Math.random().toString()
})
}
.height('100%')
.width('100%')
}
}
在HarmonyOS鸿蒙Next中,使用@ObservedV2和@Trace注解时若UI未更新,通常是由于未正确应用状态管理机制。请确认是否在ArkUI声明式框架中使用了状态变量,并确保数据变更通过响应式方式触发。检查@Trace修饰的字段是否被正确观察,且UI组件绑定了对应状态。若使用不当,数据变更可能无法通知到UI线程。
在HarmonyOS Next中,使用@ObservedV2
和@Trace
装饰的类需要确保数据更新时触发UI重新渲染。从代码来看,问题可能在于currentItem
直接引用了数组中的对象,但数组本身的引用未改变,导致UI未检测到变化。
建议尝试将currentItem
的赋值改为深拷贝或重新创建对象实例,确保每次更新时引用发生变化:
aboutToAppear(): void {
this.list = [{ name: '0' }, { name: '1' }];
this.currentItem = { ...this.list[1] }; // 使用展开运算符创建新对象
}
或者,在点击事件中更新时重新赋值currentItem
:
.onClick(() => {
this.currentItem.name = Math.random().toString();
this.currentItem = { ...this.currentItem }; // 强制更新引用
})
这样可以确保UI检测到数据变化并重新渲染。