HarmonyOS 鸿蒙Next状态管理V2

HarmonyOS 鸿蒙Next状态管理V2

V2 版本的状态管理装饰器有以下几种,都是从api12开始支持。不过问题不大,目前应用市场上架鸿蒙应用最低版本要求就是api12

@ComponentV2

和V1中的@Component装饰器一样,@ComponentV2装饰器用于装饰自定义组件:只有在该装饰器修饰的类中才能使用,也仅能使用其他V2版本的状态管理装饰器,无法在同一个自定义组件中混用V1、V2装饰器

@ObservedV2@Trace

先来看下这两个,后续介绍其他装饰器时有用到。

这两个装饰器被用来做深度观测,也就是嵌套类的变化。在 V1 版本中,我们使用@Observed@ObjectLink来实现,但有一个问题就是无法进行嵌套观测,只能观测当前层级的属性变化。V2 版本的这两个装饰器配合使用,可以实现跨嵌套层级观测。

定义一个嵌套类,使用[@ObservedV2](/user/ObservedV2)装饰需要观测的类,并且在类中使用[@Trace](/user/Trace)修饰每一个需要参与UI绘制的属性。当需要观测的类和属性较多时,写起来就比较恶心了。

还有一个非常恶心也非常麻烦的点:@ObservedV2的类实例目前不支持使用JSON.stringify进行序列化。

@Local

该装饰器修饰的变量只能在本地初始化,不能由外部传入,目的是能更好的表示组件内部的状态,不会被外部传入参数影响。

@State相比,它无法观察到class对象属性的赋值,仅能观察到对象的整体赋值,也就是说它的观测能力仅限于被装饰变量的本身。

当需要观察class对象属性的变化时,需要使用[@ObservedV2](/user/ObservedV2)[@Trace](/user/Trace)装饰器。

有一点需要注意的地方:在状态管理V2中,会给使用状态变量装饰器如@Trace@Local装饰的Date、Map、Set、Array添加一层代理用于观测API调用产生的变化,因此我们在取其中的值进行比较时,需要使用UIUtils.getTarget()获取原始对象进行比较。

@Param

可以从父组件传入,也可以在本地初始化,如果配合@Require使用,则父组件必须传入该参数,此时本地初始化的值将被覆盖。

有一点需要注意:不能在组件内部直接修改变量本身,但可以修改类对象的属性;如何类对象属性没有[@Trace](/user/Trace)修饰,修改类对象属性也不会引起 UI 刷新

当我们在组件内部直接修改变量本身时,则会提示Cannot assign to 'count' because it is a read-only property.

@Once

如果想要直接在组件内修改被[@Param](/user/Param)修饰的变量本身,可以配合[@Once](/user/Once),但是,但是,但是,被[@Once](/user/Once)装饰的变量仅能在外部初始化一次,当在外部修改该变量本身时,不会同步到子组件。看下示例:

@Event

上面说了这么多,但就是想做到像 V1中的数据双向同步怎么办?毕竟这是一个挺常见的需求。

假如不提供对应装饰器的话,我们可以很容易想到让父组件传入一个回调方法,当需要改变数据时,调用传入的回调方法,让父组件来更新数据。

在 V2 中也是这么做的:使用[@Event](/user/Event)装饰器装饰回调方法并调用,可以实现更改数据源的变量,再通过[@Local](/user/Local)的同步机制,将修改同步回[@Param](/user/Param),以此达到主动更新[@Param](/user/Param)装饰变量的效果。

文档上解释说是为了规范组件输出:

@Param标志着组件的输入,表明该变量受父组件影响,而@Event标志着组件的输出,可以通过该方法影响父组件。使用@Event装饰回调方法是一种规范,表明该回调作为自定义组件的输出。父组件需要判断是否提供对应方法用于子组件更改@Param变量的数据源。

可以直接看示例

@Monitor

可以用来监听状态变量的改变,在V1版本的@Watch中,无法实现对对象、数组中某一单个属性或数组项变化的监听,且无法获取变化之前的值。并且[@Monitor](/user/Monitor)既可以用在自定义组件中,也可以用在数据类中,可以同时监听多个对象属性,也可以精确的监听对象的某个属性。

需要注意的是:

  • 监听的变量需要被@Local@Param@Provider@Consumer@Computed装饰,未被状态变量装饰器装饰的变量在变化时无法被监听。@Monitor可以同时监听多个状态变量,这些变量名之间用","隔开。
  • 监听的状态变量为类对象时,仅能监听对象整体的变化。监听类属性的变化需要类属性被@Trace装饰,未被@Trace装饰的属性的变化无法被监听。
  • 支持对数组中的项进行监听,包括多维数组,对象数组。@Monitor无法监听内置类型(Array、Map、Date、Set)的API调用引起的变化。当@Monitor监听数组整体时,只能观测到数组整体的赋值。可以通过监听数组的长度变化来判断数组是否有插入、删除等变化。当前仅支持使用"."的方式表达深层属性、数组项的监听。

在控件中

这个也有一点需要注意,当我们对类对象重新赋值,但是赋值前后类对象的属性值不变,也不会触发[@Monitor](/user/Monitor)回调。

还有一点需要注意的是监听的生效和失效时间:

  • 当在组件中使用时,[@Monitor](/user/Monitor)会在状态变量初始化完成之后生效,并在组件销毁时失效。
  • 当在类中使用时,[@Monitor](/user/Monitor)会在类创建完成后生效,在类销毁时失效。这个时机晚于类的constructor,早于自定义组件的aboutToAppear。然而由于类的实际销毁释放依赖于垃圾回收机制,因此会出现即使所在自定义组件已经销毁,类却还未及时销毁,导致类中定义的@Monitor仍在监听变化的情况。

@Computed

千呼万唤始出来的装饰器,谁家的状态管理还没有计算属性哇

该装饰器为方法装饰器,装饰getter方法。[@Computed](/user/Computed)会检测被计算的属性变化,当被计算的属性变化时,[@Computed](/user/Computed)只会被求解一次。

该装饰器既可以在组件中使用,也可以在数据类中使用。

可以在控制台看到,虽然我们展示多次,但控制台只打印了一次信息;当我们分别点击修改简单属性修改对象属性时,控制台也是打印一次信息。

这里还有个注意点:@Computed装饰的属性可以初始化@Param

参考文档:鸿蒙-状态管理V2 - 知乎


更多关于HarmonyOS 鸿蒙Next状态管理V2的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

鸿蒙Next状态管理V2基于ArkTS实现,采用基于响应式的状态机制。核心特性包括:

  1. @State:组件内状态管理
  2. @Prop:父子组件单向同步
  3. @Link:父子组件双向绑定
  4. @Provide/@Consume:跨层级组件通信
  5. @Observed/@ObjectLink:用于嵌套对象观察

新增功能支持状态变量类型扩展和更精细的渲染控制。状态变更触发UI自动更新,无需手动操作DOM。适用于鸿蒙应用级和组件级状态共享场景。

更多关于HarmonyOS 鸿蒙Next状态管理V2的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS Next的状态管理V2版本确实带来了许多改进和新特性。以下是对主要装饰器的简要总结:

  1. @ComponentV2:基础组件装饰器,必须使用V2系列装饰器,不能与V1混用。

  2. @ObservedV2@Trace

    • 实现深度嵌套观测
    • 需要配合使用,@ObservedV2修饰类,@Trace修饰属性
    • 目前不支持JSON序列化
  3. @Local

    • 仅限组件内部初始化
    • 只能观测变量整体赋值,不能观测对象属性变化
  4. @Param

    • 可从父组件传入或本地初始化
    • 组件内部不能直接修改变量本身,但可修改对象属性(需@Trace修饰)
  5. @Once

    • 只允许外部初始化一次
    • 拦截数据源赋值操作,不影响属性修改
  6. @Event

    • 规范组件输出
    • 通过回调实现父子组件通信
    • 修改是异步的
  7. @Monitor

    • 强大的监听能力
    • 支持精确监听对象属性
    • 可获取变化前后的值
  8. @Computed

    • 计算属性装饰器
    • 自动缓存计算结果
    • 可用于组件或数据类

V2版本解决了V1中许多痛点,特别是嵌套观测和计算属性等功能的加入,使状态管理更加完善。不过使用时需要注意各装饰器的特性和限制,如@ObservedV2的序列化问题、@Local的观测范围等。

回到顶部