文章目录一、引言二、什么是 State三、监听基本数据类型四、监听对象类型五、监听嵌套对象5.1 Observed5.2 ObjectLink5.4 Track5.5 与 Observed 的区别六、总结对比七、关键要点这是一个使用鸿蒙技术开发的本地原生记账应用非常适合大家用来练手。相关源码已上传至 Github点击此处查看项目。欢迎大家交流、指正也欢迎提交 PR。一、引言在鸿蒙HarmonyOS应用开发中ArkTS 框架提供了一套强大的响应式编程模型。其中State装饰器是实现组件内部状态管理、驱动 UI 自动刷新的核心工具。本文将深入浅出地讲解State的使用方法、监听机制以及最佳实践帮助你快速掌握这一关键特性。二、什么是 StateState是 HarmonyOS ArkTS 框架中用于管理组件内部状态的核心装饰器它实现了数据驱动 UI 的响应式编程。被State修饰的变量变化时依赖该变量的 UI 组件会自动重新渲染保持数据与界面的同步。其底层基于依赖收集和变更通知机制组件渲染时框架会收集State变量的 UI 依赖关系当变量被修改时框架会通知所有依赖方执行最小化更新从而高效地刷新界面。三、监听基本数据类型对于boolean、string、number等基础类型直接赋值即可被框架观察到并触发 UI 刷新。EntryComponentstruct BasicTypeDemo{Statecount:number0;Statename:stringHello;build(){Column({space:20}){Text(Count:${this.count}).fontSize(30)Text(Name:${this.name}).fontSize(30)Button(Increment).onClick((){this.count;// 可观察触发UI刷新})Button(Change Name).onClick((){this.nameArkTS;// 可观察触发UI刷新})}}}运行效果如下四、监听对象类型State可以观察到对象自身的赋值以及属性赋值的变化但需要注意必须通过赋值操作修改对象或其属性直接修改嵌套子属性第二层及以下State无法监测。interfaceIUser{name:stringage:number}EntryComponentstruct ObjectDemo{Stateuser:IUser{name:Alice,age:25};build(){Column({space:20}){Text(Name:${this.user.name}).fontSize(20)Text(Age:${this.user.age}).fontSize(20)Button(Update Age).onClick((){// ✅ 属性赋值可观察this.user.agethis.user.nameBeer})Button(Replace Object).onClick((){// ✅ 整体赋值可观察this.user{name:Bob,age:30};})}}}五、监听嵌套对象示例嵌套对象结构classPet{name:string阿旺;age:number2;}classPerson{name:stringJerry;age:number18;pet:PetnewPet();}EntryComponentstruct NestedDemo{Stateperson:PersonnewPerson();build(){Column({space:20}){Text(name:${this.person.name}).fontSize(20)Text(age:${this.person.age}).fontSize(20)Text(pet name:${this.person.pet.name}).fontSize(20)Text(pet age:${this.person.pet.age}).fontSize(20)Button(改变人的年龄).onClick((){// ✅ 第一层变化State可观察this.person.age})Button(改变宠物的年龄).onClick((){// ❌ 不可观察this.person.pet.age})}}}上述代码中当点击第二个按钮改变宠物的年龄时对this.person.pet.age重新进行了赋值但是页面并没有发生变化。这是因为State只支持一层观察无法递归监听嵌套对象深层属性的变化。对于嵌套对象二层及以下属性的变化必须配合Observed和ObjectLink装饰器。5.1 ObservedObserved是一个类装饰器用于标记一个类为可观察的。当类被Observed装饰后其实例的属性变化可以被框架追踪到即使这些属性是嵌套的深层属性。通常与ObjectLink配合使用解决State无法监听嵌套对象深层变化的限制。5.2 ObjectLinkObjectLink是一个变量装饰器用于在子组件中接收父组件传递过来的Observed装饰类的实例。它会在子组件中建立对父组件数据的引用当被引用的属性发生变化时子组件会自动刷新。当数据结构包含多层嵌套如对象中包含对象、数组等且需要监听深层属性的变化时使用ObservedObjectLink组合是最佳实践。父组件用State持有顶层对象子组件用ObjectLink接收嵌套对象从而实现深度响应式监听。下面使用 Observed ObjectLink对上面的嵌套对象结构进行改造// 使用Observed装饰被嵌套的类ObservedclassPet{name:string阿旺;age:number2;}classPerson{name:stringJerry;age:number18;pet:PetnewPet();}EntryComponentstruct NestedDemo{Stateperson:PersonnewPerson();build(){Column({space:20}){Text(person name:${this.person.name}).fontSize(20)Text(person age:${this.person.age}).fontSize(20)PetComponent({pet:this.person.pet})Button(改变人的年龄).onClick((){this.person.age})Button(改变宠物的年龄).onClick((){// 现在可以观察到嵌套属性的变化this.person.pet.age})}}}Componentstruct PetComponent{ObjectLinkpet:Pet;build(){Column({space:20}){Text(component pet name:${this.pet.name}).fontSize(20)Text(component pet age:${this.pet.age}).fontSize(20)}}}5.4 Track上述代码虽然实现了对深层次数据变化的监听但依然存在问题。为了验证这个问题我们对代码进行如下改造// ...EntryComponentstruct NestedDemo{//...isRender(tag:string):number{console.log(Text${tag}is rendered);return20;}build(){Column({space:20}){Text(person name:${this.person.name}).fontSize(this.isRender(person name))Text(person age:${this.person.age}).fontSize(this.isRender(person age))PetComponent({pet:this.person.pet})Button(改变人的年龄).onClick((){this.person.age})Button(改变宠物的年龄).onClick((){this.person.pet.age})}}}//...添加了isRender(tag: string)方法打开 Log 窗口点击改变人的年龄按钮可以看到问题分析咱们只修改了人的年龄但人名那个文本也被重新渲染了这明显不合适造成了过度渲染。这种过度渲染会带来以下问题性能浪费不必要的UI更新消耗CPU和GPU资源响应延迟大量不必要的渲染操作会降低应用响应速度电池消耗频繁的UI更新会增加设备功耗要想解决这个问题可以使用Track装饰器。Track装饰器是鸿蒙ArkTS框架中用于精细化状态管理的工具它能够精确追踪对象内部特定属性的变化仅在标记的属性发生变更时触发UI更新。这解决了传统状态管理如State中“过度渲染”的问题——传统方式下即使对象只有一个属性变化也会导致整个组件重新渲染造成性能浪费。在类定义中使用Track装饰需要被观察的属性//...classPerson{Trackname:stringJerry;Trackage:number18;Trackpet:PetnewPet();}EntryComponentstruct NestedDemo{//...}//...上面咱们对name、age、pet三个属性都使用Track进行了修饰可能你会疑惑咱们只是修改的age属性的值其他两个为啥也要用Track修饰呢这是是因为未使用Track标记的属性不能在 UI 组件中使用否则会报错。name、pet属性咱们都用在UI组件中使用了为了防止报错所以都用Track进行了修饰。注意可以在非 UI 组件中使用非Track装饰的属性如事件回调函数中、生命周期函数中等。5.5 与 Observed 的区别Observed是类装饰器作用于整个类使类的所有属性都可被观察。Track是属性装饰器作用于类中的具体属性只标记需要被观察的字段。当只需要监听嵌套对象中的某几个属性时使用Track更加轻量和精确避免不必要的性能开销。六、总结对比数据类型监听方式可观察的修改注意事项基本类型number/string/booleanState直接赋值最基础的响应式用法性能最佳对象第一层属性State整体赋值、属性赋值嵌套属性第二层及以下不可观察嵌套对象第二层及以下ObservedObjectLink深层属性变化可观察类需用Observed装饰子组件用ObjectLink接收嵌套对象精确控制Track仅标记的属性变化可观察避免过度渲染提升性能未标记的属性不能在 UI 中使用七、关键要点State变量必须初始化且通过this.xxx value修改支持基本类型和对象及对象第一层属性的变化监听。嵌套对象的深层变化需要Observed/ObjectLink配合实现深度观察父组件用State持有顶层对象子组件用ObjectLink接收嵌套对象。Track装饰器用于精确控制属性观察仅标记的属性变化才触发 UI 更新可有效避免过度渲染问题但未标记Track的属性不能在 UI 中使用否则会导致 JSCrash。