在HarmonyOS V1版本中,状态管理装饰器是用于简化组件状态管理的核心工具,通过注解方式实现数据与UI的自动绑定。这些装饰器基于ArkUI框架设计,支持声明式编程范式,开发者无需手动处理状态更新与界面刷新的逻辑。具体内容和示例如下:

@State装饰器:组件内状态

概述

@State装饰的变量与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型并完成本地初始化;若需从父组件初始化,也可选择使用命名参数机制完成赋值。

@State装饰的变量拥有以下特点:

  • @State装饰的变量生命周期与其所属自定义组件的生命周期相同。

装饰器使用规则说明

@State变量装饰器说明
装饰器参数
同步类型不与父组件中任何类型的变量同步。
允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。

支持Date类型、undefined和null类型。以及ArkUI框架定义的联合类型LengthResourceStrResourceColor类型。

类型必须指定。

不支持any。

API version 11及以上支持MapSet类型以及上述支持类型的联合类型,比如string | number, string | undefined 或者 ClassA | null。

注意:

当使用undefined和null的时候,建议显式指定类型,遵循TypeScript类型校验。比如:支持@State a : string | undefined = undefined;不支持@State a: string = undefined。

被装饰变量的初始值必须本地初始化。

变量的传递/访问规则说明

传递/访问说明
从父组件初始化

可以从父组件或本地初始化。

父组件传入非undefined值时覆盖本地初始值,否则使用@State的本地初始值。

支持父组件中的常规变量以及装饰器装饰的状态变量:@State、@Link@Prop@Provide@Consume@ObjectLink@StorageLink@StorageProp@LocalStorageLink@LocalStorageProp,初始化@State。需要注意:父组件传入的外部变量对@State初始化时,仅作为初始值,后续变量的变化不会同步至@State。

用于初始化子组件@State装饰的变量支持初始化子组件的常规变量、@State、@Link、@Prop、@Provide。
是否支持组件外访问不支持,只能在组件内访问。

初始化规则图示

@Prop装饰器:父子单向同步

@Prop装饰的变量可以和父组件建立单向同步关系。@Prop变量允许在本地修改,但修改后的变化不会同步回父组件

概述

@Prop装饰的变量和父组件建立单向的同步关系:

  • @Prop装饰的变量允许本地修改,但修改不会同步回父组件。

  • 当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。

限制条件

  • @Prop装饰变量时会进行深拷贝,在拷贝的过程中除了基本类型、Map、Set、Date、Array外,都会丢失类型。例如PixelMap等通过NAPI提供的复杂类型,由于有部分实现在Native侧,因此无法在ArkTS侧通过深拷贝获得完整的数据。

装饰器使用规则说明

@Prop变量装饰器说明
装饰器参数无。
同步类型

单向同步。对父组件状态变量值的修改,将同步给子组件@Prop装饰的变量,子组件@Prop装饰的变量的修改不会同步到父组件的状态变量上。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。

不支持any,支持undefined和null。

支持Date类型

支持ArkUI框架定义的联合类型LengthResourceStrResourceColor类型。

必须指定类型。

@Prop和数据源类型需要相同,有以下三种情况:

- @Prop装饰的变量和@State以及其他装饰器同步时双方的类型必须相同

- @Prop装饰的变量和@State以及其他装饰器装饰的数组的项同步时 ,@Prop的类型需要和@State装饰的数组的数组项相同,比如@Prop : T和@State : Array<T>

- 当父组件状态变量为Object或者class时,@Prop装饰的变量和父组件状态变量的属性类型相同

API11及以上支持MapSet类型,以及联合类型,比如string | number, string | undefined 或者 ClassA | null

注意

当使用undefined和null的时候,建议显式指定类型,遵循TypeScript类型校验,比如:@Prop a : string | undefined = undefined是支持的,不支持@Prop a: string = undefined。

嵌套传递层数在组件复用场景,建议@Prop深度嵌套数据不要超过5层,嵌套太多会导致深拷贝占用的空间过大以及GarbageCollection(垃圾回收),引起性能问题,此时更建议使用@ObjectLink
被装饰变量的初始值允许本地初始化。如果在API 11中和@Require结合使用,则必须父组件构造传参。

变量的传递/访问规则说明

装饰器使用规则说明
从父组件初始化如果本地有初始化,则是可选的,初始化行为和@State保持一致。没有的话,则必选,支持父组件中的常规变量(常规变量对@Prop赋值,只是数值的初始化,常规变量的变化不会触发UI刷新。只有状态变量才能触发UI刷新)、@State@Link、@Prop、@Provide@Consume@ObjectLink@StorageLink@StorageProp@LocalStorageLink@LocalStorageProp去初始化子组件中的@Prop变量。
用于初始化子组件@Prop支持初始化子组件中的常规变量、@State、@Link、@Prop、@Provide。
是否支持组件外访问@Prop装饰的变量是私有的,只能在组件内访问。

初始化规则图示:

@Link装饰器:父子双向同步

子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。

概述

@Link装饰的变量与其父组件中的数据源共享相同的值。

装饰器使用规则说明

@Link变量装饰器说明
装饰器参数无。
同步类型

双向同步。

父组件状态变量与子组件@Link建立双向同步,当其中一方改变时,另一方也会同步更新。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。

支持Date类型

支持ArkUI框架定义的联合类型LengthResourceStrResourceColor类型。

类型必须指定,且与双向绑定状态变量类型相同。

不支持any类型。

API version 11及以上支持支持MapSet类型以及上述支持类型的联合类型。例如:string | number, string | undefined或者ClassA | null。

注意:

使用undefined和null的时候,建议显式指定类型,遵循TypeScript类型校验。例如:@Link a : string | undefined。

被装饰变量的初始值无,禁止本地初始化。

变量的传递/访问规则说明

传递/访问说明
从父组件初始化和更新

必选。

- 与父组件@State, @StorageLink和@Link 建立双向绑定。允许父组件中@State、@Link、@Prop@Provide@Consume@ObjectLink@StorageLink@StorageProp@LocalStorageLink@LocalStorageProp装饰变量初始化子组件@Link。

- 从API version 9开始,@Link子组件从父组件初始化@State的语法为Comp({ aLink: this.aState }),同样支持Comp({aLink: $aState})。

用于初始化子组件允许,可用于初始化常规变量、@State、@Link、@Prop、@Provide。
是否支持组件外访问私有,只能在所属组件内访问。

初始化规则示意图

@Provide装饰器和@Consume装饰器:与后代组件双向同步

@Provide和@Consume,应用于与后代组件的双向数据同步、状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递。

其中@Provide装饰的变量是在祖先组件中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费(绑定)”祖先组件提供的变量。

概述

@Provide/@Consume装饰的状态变量有以下特性:

  • @Provide装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide的方便之处在于,开发者不需要多次在组件之间传递变量。

  • 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。

  • @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。

// 通过相同的变量名绑定
@Provide age: number = 0;
@Consume age: number;

// 通过相同的变量别名绑定
@Provide('a') id: number = 0;
@Consume('a') age: number;

@Provide和@Consume通过相同的变量名或者相同的变量别名绑定时,@Provide装饰的变量和@Consume装饰的变量是一对多的关系。不允许在同一个自定义组件内,包括其子组件中声明多个同名或者同别名的@Provide装饰的变量,@Provide的属性名或别名需要唯一且确定,如果声明多个同名或者同别名的@Provide装饰的变量,会发生运行时报错。

装饰器说明

@State的规则同样适用于@Provide,差异为@Provide还作为多层后代的同步源。

@Provide变量装饰器说明
装饰器参数

别名:常量字符串,可选。

如果指定了别名,则通过别名来绑定变量;如果未指定别名,则通过变量名绑定变量。

同步类型

双向同步。

从@Provide变量到所有@Consume变量以及相反的方向的数据同步。双向同步的操作与@State和@Link的组合相同。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。

支持Date类型

支持ArkUI框架定义的联合类型LengthResourceStrResourceColor类型。

必须指定类型。

@Provide变量和@Consume变量的类型必须相同。

不支持any类型。

API version 11及以上支持MapSet类型以及上述支持类型的联合类型。例如:string | number, string | undefined或者ClassA | null。

注意:

当使用undefined和null的时候,建议显示指定类型,遵循TypeScript类型校验。例如:推荐@Provide a : string | undefined = undefined,不推荐@Provide a: string = undefined。

被装饰变量的初始值必须指定。
支持allowOverride参数允许重写,只要声明了allowOverride,则别名和属性名都可以被Override。
@Consume变量装饰器说明
装饰器参数

别名:常量字符串,可选。

如果提供了别名,则必须有@Provide的变量和其有相同的别名才可以匹配成功;否则,则需要变量名相同才能匹配成功。

同步类型双向同步:从@Provide变量(具体请参见@Provide)到所有@Consume变量,以及相反的方向。双向同步操作与@State和@Link的组合相同。
允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。

支持Date类型

支持ArkUI框架定义的联合类型LengthResourceStrResourceColor类型。

必须指定类型。

@Provide变量和@Consume变量的类型必须相同。

API version 20之前,@Consume装饰的变量,在其父组件或者祖先组件上,必须有对应的属性和别名的@Provide装饰的变量。

不支持any类型。

API version 11及以上支持MapSet类型以及上述支持类型的联合类型。例如:string | number, string | undefined或者ClassA | null。

注意:

当使用undefined和null的时候,建议显示指定类型,遵循TypeScript类型校验。例如:@Consume a : string | undefined。

被装饰变量的初始值从API version 20开始,@Consume支持设置默认值。若存在匹配成功的@Provide,则会使用@Provide的变量值作为初始值。

变量的传递/访问规则说明

@Provide传递/访问说明
从父组件初始化和更新可选,允许父组件中常规变量(常规变量对@Provide赋值,只是数值的初始化,常规变量的变化不会触发UI刷新,只有状态变量才能触发UI刷新)、@State@Link@Prop、@Provide、@Consume、@ObjectLink@StorageLink@StorageProp@LocalStorageLink@LocalStorageProp装饰的变量装饰变量初始化子组件@Provide。
用于初始化子组件允许,可用于初始化@State、@Link、@Prop、@Provide。
和父组件同步否。
和后代组件同步和@Consume双向同步。
是否支持组件外访问私有,仅可以在所属组件内访问。

@Provide初始化规则图示

@Consume传递/访问说明
从父组件初始化和更新禁止。
用于初始化子组件允许,可用于初始化@State、@Link、@Prop、@Provide。
和祖先组件同步和@Provide双向同步。
是否支持组件外访问私有,仅可以在所属组件内访问

@Consume初始化规则图示

@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

上文所述的装饰器(包括@State、@Prop、@Link、@Provide和@Consume装饰器)仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。

概述

@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:

  • 使用new创建被@Observed装饰的类,可以被观察到属性的变化。

  • 子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。

  • @Observed用于嵌套类场景中,观察对象类属性变化,要配合自定义组件使用,如果要做数据双/单向同步,需要搭配@ObjectLink或者@Prop使用。

装饰器说明

@Observed类装饰器说明
装饰器参数无。
类装饰器装饰class。需要放在class的定义前,使用new创建类对象。
@ObjectLink变量装饰器说明
装饰器参数无。
允许装饰的变量类型

API version 19之前,必须为被@Observed装饰的class实例。

API version 19及以后,@ObjectLink也可以被makeV1Observed的返回值初始化。

@ObjectLink不支持简单类型,如果开发者需要使用简单类型,可以使用@Prop

支持继承Date、Array的class实例,API11及以上支持继承MapSet的class实例。

API11及以上支持@Observed装饰类和undefined或null组成的联合类型,比如ClassA | ClassB, ClassA | undefined 或者 ClassA | null。

@ObjectLink的属性可以被改变的,但不允许整体赋值,即@ObjectLink装饰的变量是只读的。

被装饰变量的初始值不允许。

@ObjectLink装饰的数据为可读示例。

// 允许@ObjectLink装饰的数据属性赋值
this.objLink.a= ...
// 不允许@ObjectLink装饰的数据自身赋值
this.objLink= ...

变量的传递/访问规则说明

@ObjectLink传递/访问说明
从父组件初始化

必须指定。

初始化@ObjectLink装饰的变量必须同时满足以下场景:

- 类型必须是@Observed装饰的class。

- 初始化的数值需要是数组项,或者class的属性。

- 同步源的class或者数组必须是@State@Link@Provide@Consume或者@ObjectLink装饰的数据。

与源对象同步双向。
可以初始化子组件允许,可用于初始化常规变量、@State、@Link、@Prop、@Provide

初始化规则图示

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐