学习目标:
在鸿蒙HarmonyOS应用开发中,@State装饰器是管理组件状态的重要工具,尤其在处理对象数组时,它能确保UI与数据模型的同步更新。本文档将深入探讨如何利用@State有效地执行对象数组的增删操作以及属性更新,确保状态变化的正确反映。
项目源码
1. 声明对象数组:
class person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
@State p: person = new person('王五', 20)
@State gf: person[] = [new person('张1', 20), new person('张2', 20)]
2. 对象数组的增删操作:
添加元素
向@State修饰的对象数组中添加元素是直接有效的,因为push方法会修改数组的引用,从而触发状态更新。
Button('add')
.onClick(() => {
this.gf.push(new person('张3', 20)); // 正确触发状态更新
})
删除元素
类似地,使用pop方法从数组末尾移除元素也会改变数组引用,自动触发UI更新。
Button('delete')
.onClick(() => {
this.gf.pop(); // 正确触发状态更新
})
频繁的增删操作可能导致频繁的重渲染,应注意性能优化。
尽量避免在事件处理器中直接修改状态,考虑使用函数来封装修改逻辑,保持状态管理的清晰和纯净。
3.对象属性更新:
直接修改数组中的对象属性不会触发@State的更新,因为对象是引用类型,数组中的引用并没有改变。正确的做法是创建新对象并替换旧的对象引用。
直接修改数组对象的属性(无效)
Column() {
ForEach(
this.gf,
(item: person, index?: number) => {
Text(`${item.name}:${item.age}`)
.fontColor('#44ec0a73')
.fontSize(50)
.lineHeight(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.gf[index].age = this.gf[index].age + 1;
})
}
)
}
}
解决方案:深拷贝和状态更新
这里,使用了扩展运算符…进行浅拷贝,并创建了一个新对象,然后用splice方法替换掉旧的对象实例,以触发@State的更新。
Column() {
ForEach(
this.gf,
(item: person, index?: number) => {
Text(`${item.name}:${item.age}`)
.fontColor('#44ec0a73')
.fontSize(50)
.lineHeight(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
const updatedPerson = { ...item, age: item.age + 1 };
this.gf.splice(index, 1, updatedPerson); // 删除旧对象,插入新对象
})
}
)
}
}
注意事项
状态的深拷贝:对于对象或数组,务必创建新实例以触发@State更新。
数组操作:使用push、pop等方法直接操作数组,因为它们会改变数组的引用,而forEach内的对象属性更新需要使用深拷贝。
性能:频繁的深拷贝和数组操作可能影响性能,因此,对于大型数据集,应考虑优化策略,如使用immer库或自定义缓存机制。
4.心得:
@State装饰器是鸿蒙HarmonyOS开发中实现响应式UI的关键工具,它简化了状态管理,提高了代码的可读性和可维护性
但是数组中的对象属性无法触发视图更新,要采取其他办法触发@state视图更新。
此外,嵌套类型也无法刷新视图,具体可看danfengw的这篇学习链接: 鸿蒙Harmony(八)ArkUI–状态管理器之@State