ArkUI状态管理
状态管理(V1稳定版)
开发者可以使用当前比较完整的状态管理V1版本进行应用开发。
装饰器总览
ArkUI状态管理V1提供了多种装饰器,通过使用这些装饰器,状态变量不仅可以观察在组件内的改变,还可以在不同组件层级间传递,比如父子组件、跨组件层级,也可以观察全局范围内的变化。根据状态变量的影响范围,将所有的装饰器可以大致分为:
- 管理组件拥有状态的装饰器:组件级别的状态管理,可以观察组件内变化,和不同组件层级的变化,但需要唯一观察同一个组件树上,即同一个页面内。
- 管理应用拥有状态的装饰器:应用级别的状态管理,可以观察不同页面,甚至不同UIAbility的状态变化,是应用内全局的状态管理。
从数据的传递形式和同步类型层面看,装饰器也可分为:
- 只读的单向传递;
- 可变更的双向传递。
图示如下,具体装饰器的介绍,可详见管理组件拥有的状态和管理应用拥有的状态。开发者可以灵活地利用这些能力来实现数据和UI的联动。
上图中,Components部分的装饰器为组件级别的状态管理,Application部分为应用的状态管理。开发者可以通过@StorageLink/@LocalStorageLink实现应用和组件状态的双向同步,通过@StorageProp/@LocalStorageProp实现应用和组件状态的单向同步。
管理组件拥有的状态,即图中Components级别的状态管理:
- @State:@State装饰的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。当其数值改变时,会引起相关组件的渲染刷新。
- @Prop:@Prop装饰的变量可以和父组件建立单向同步关系,@Prop装饰的变量是可变的,但修改不会同步回父组件。
- @Link:@Link装饰的变量可以和父组件建立双向同步关系,子组件中@Link装饰变量的修改会同步给父组件中建立双向数据绑定的数据源,父组件的更新也会同步给@Link装饰的变量。
- @Provide/@Consume:@Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。
- @Observed:@Observed装饰class,需要观察多层嵌套场景的class需要被@Observed装饰。单独使用@Observed没有任何作用,需要和@ObjectLink、@Prop联用。
- @ObjectLink:@ObjectLink装饰的变量接收@Observed装饰的class的实例,应用于观察多层嵌套场景,和父组件的数据源构建双向同步。
管理应用拥有的状态,即图中Application级别的状态管理:
- AppStorage是应用程序中的一个特殊的单例LocalStorage对象,是应用级的数据库,和进程绑定,通过@StorageProp和@StorageLink装饰器可以和组件联动。
- AppStorage是应用状态的“中枢”,将需要与组件(UI)交互的数据存入AppStorage,比如持久化数据PersistentStorage和环境变量Environment。UI再通过AppStorage提供的装饰器或者API接口,访问这些数据。
- 框架还提供了LocalStorage,AppStorage是LocalStorage特殊的单例。LocalStorage是应用程序声明的应用状态的内存“数据库”,通常用于页面级的状态共享,通过@LocalStorageProp和@LocalStorageLink装饰器可以和UI联动。
其他状态管理V1功能
@Watch用于监听状态变量的变化。
$$运算符:给内置组件提供TS变量的引用,使得TS变量和内置组件的内部状态保持同步。
状态管理(V2试用版)
为了增强状态管理V1版本的部分能力,例如深度观察、属性级更新等,ArkUI推出状态管理(V2试用版)供开发者体验试用。
状态管理V1现状以及V2优点
状态管理V1使用代理观察数据,当创建一个状态变量时,同时也创建了一个数据代理观察者。该观察者可感知代理变化,但无法感知实际数据变化,因此在使用上有如下限制:
- 状态变量不能独立于UI存在,同一个数据被多个视图代理时,在其中一个视图的更改不会通知其他视图更新。
- 只能感知对象属性第一层的变化,无法做到深度观测和深度监听。
- 在更改对象中属性以及更改数组中元素的场景下存在冗余更新的问题。
- 装饰器间配合使用限制多,不易用。组件中没有明确状态变量的输入与输出,不利于组件化。
状态管理V2将观察能力增强到数据本身,数据本身就是可观察的,更改数据会触发相应的视图的更新。相较于状态管理V1,状态管理V2有如下优点:
- 状态变量独立于UI,更改数据会触发相应视图的更新。
- 支持对象的深度观测和深度监听,且深度观测机制不影响观测性能。
- 支持对象中属性级精准更新及数组中元素的最小化更新。
- 装饰器易用性高、拓展性强,在组件中明确输入与输出,有利于组件化。
装饰器总览
状态管理(V2试用版)提供了一套全新的装饰器。
- @ObservedV2:@ObservedV2装饰器装饰class,使得被装饰的class具有深度监听的能力。@ObservedV2和@Trace配合使用可以使class中的属性具有深度观测的能力。
- @Trace:@Trace装饰器装饰被@ObservedV2装饰的class中的属性,被装饰的属性具有深度观测的能力。
- @ComponentV2:使用@ComponentV2装饰的struct中能使用新的装饰器。例如:@Local、@Param、@Event、@Once、@Monitor、@Provider、@Consumer。
- @Local:@Local装饰的变量为组件内部状态,无法从外部初始化。
- @Param:@Param装饰的变量作为组件的输入,可以接受从外部传入初始化并同步。
- @Once:@Once装饰的变量仅初始化时同步一次,需要与@Param一起使用。
- @Event:@Event装饰方法类型,作为组件输出,可以通过该方法影响父组件中变量。
- @Monitor:@Monitor装饰器用于@ComponentV2装饰的自定义组件或@ObservedV2装饰的类中,能够对状态变量进行深度监听。
- @Provider和@Consumer:用于跨组件层级双向同步。
- @Computed:计算属性,在被计算的值变化的时候,只会计算一次。主要应用于解决UI多次重用该属性从而重复计算导致的性能问题。
- !!语法:双向绑定语法糖。
使用限制
由于状态管理V2采用了和状态管理V1不同的实现,因此不能将状态管理框架V2和状态管理V1混合使用,这项限制包括如下场景:
- 将V2版本的装饰器装饰的变量传递给V1版本装饰器装饰的变量。
- 将V1版本装饰器@Observed、@Track与V2版本装饰器@ObservedV2、@Trace混合使用。
- 将V1版本装饰器@State、@Prop、@Link、@ObjectLink、@Provide、@Consume、@StorageLink、@StorageProp、@LocalStorageLink、@LocalStorageProp、@Watch等在@ComponentV2装饰的自定义组件中使用。
- 将V2版本装饰器@Local、@Param、@Once、@Event、@Monitor、@Provider、@Consumer在@Component装饰的自定义组件中使用。
- 将@Component与@ComponentV2同时使用。
- 在@Component装饰的自定义组件中通过@State、@Prop、@Link、@Provide、@Consume、@StorageLink、@StorageProp、@LocalStorageLink、@LocalStorageProp装饰的变量并且该变量的类型为@ObservedV2装饰的类。
- 在@ComponentV2装饰的自定义组件中通过@Param、@Local、@Event、@Provider()、@Consumer()装饰的变量并且该变量的类型为@Observed装饰的类。
将V2装饰器与V1装饰器混合使用,会出现未定义行为,表现为冗余刷新、失去深度观测能力、失去自身属性观测能力、失去属性级更新能力等。因此,不能将状态管理V2与状态管理V1在以上提到的场景混合使用。