继上篇文章鸿蒙开发中V2状态管理的使用(上)之后,本篇说一下其他几个V2版本装饰器。

完整使用方法请参考官方文档:状态管理(V2)

本文最后将附上示例代码


1、@Event:规范组件输出

由于 @Param 装饰的变量在本地无法更改,使用 @Event 装饰器装饰回调方法并调用,可以实现更新数据源的变量,再通过 @Local 的同步机制,将修改同步回 @Param 装饰的变量,以此达到主动更新 @Param 装饰变量的效果。

@Event 主要配合 @Param 实现数据的双向同步

示例代码如下:

@Entry
@ComponentV2
struct Event_Case {
  @Local num: number = 1
  build() {
    Column({ space: 20}){
      Column({ space: 15}){
        Text('父组件').fontSize(20)
        Text(`${this.num}`).fontSize(18)
      }
      .width('90%')
      .padding(20)
      .border({width: 2, color: "#000", radius: 15})
      Child({
        num: this.num,
        changeNum: () => this.num += 1
      })
    }
    .padding({ top: 40})
    .height('100%')
    .width('100%')
  }
}

@ComponentV2
struct Child {
  @Param num: number = 1
  @Event changeNum: (val: number) => void
  build() {
    Column({ space: 10}){
      Text('子组件').fontSize(20)
      Text(`${this.num}`).fontSize(18)
      Button('修改 num')
        .onClick(() => this.changeNum(this.num))
    }
    .width('90%')
    .padding(10)
    .border({width: 2, color: "#000", radius: 15})
  }
}

效果如下:

2、@Monitor:状态变量修改异步监听

该装饰器类似 V1 中的 @Watch,但是 @Watch 只能监听单个状态变量,而且观察能力为一层;而 @Monitor 可以同时监听多个状态变量,而且具有深度监听的能力,具体对比如下:

用法 @Watch @Monitor
参数 回调方法名。 监听状态变量名、属性名。
监听目标数 只能监听单个状态变量。 能同时监听多个状态变量。
监听能力 跟随状态变量观察能力(一层)。 跟随状态变量观察能力(深层)。
能否获取变化前的值 不能获取变化前的值。 能获取变化前的值。
监听条件 监听对象为状态变量。 监听对象为状态变量或为@Trace装饰的类成员属性。
使用限制 仅能在@Component装饰的自定义组件中使用。 能在@ComponentV2装饰的自定义组件中使用,也能在@ObservedV2装饰的类中使用。

使用方法如下:

(1)监听多个变量,并获取变化前后的值

@Monitor监听的变量需要被@Local@Param@Provider@Consumer@Computed装饰,未被状态变量装饰器装饰的变量在变化时无法被监听。如果同时监听多个状态变量,这些变量名之间用","隔开。

@Entry
@ComponentV2
struct Monitor_Case {
  @Local message: string = 'Hello World';
  @Local num: number = 0

  @Monitor('message', 'num')
  dataChange(monitor: IMonitor) {
    monitor.dirty.forEach((path: string) => {
      console.warn(`${path} changed from ${monitor.value(path)?.before} to ${monitor.value(path)?.now}`);
    });
  }

  build() {
    Column() {
      Text(this.message).fontSize(20)
      Text(`${this.num}`).fontSize(20)
      Button('修改变量')
        .onClick(() => {
          this.message += '#'
          this.num += 1
        })
    }
    .height('100%')
    .width('100%')
    .padding({ top: 50 })
  }
}

效果如下:

(2)@Monitor监听的状态变量为类对象时,仅能监听对象整体的变化。监听类属性的变化需要类属性被@Trace装饰。

class Person {
  public name: string;
  public age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

@Entry
@ComponentV2
struct Monitor_Case {
  @Local message: string = 'Hello World';
  @Local num: number = 0
  @Local person: Person = new Person('张三', 18);

  @Monitor('message', 'num', 'person')
  dataChange(monitor: IMonitor) {
    monitor.dirty.forEach((path: string) => {
      console.warn(`${path} changed from ${JSON.stringify(monitor.value(path)?.before)} to ${JSON.stringify(monitor.value(path)?.now)}`);
    });
  }

  build() {
    Column() {
      Text(this.message).fontSize(20)
      Text(`${this.num}`).fontSize(20)
      Text(this.person.name).fontSize(20)
      Button('修改变量')
        .onClick(() => {
          this.message += '#'
          this.num += 1
          // this.person.name += "*" // 无法监听到变化
          this.person = new Person('李四', 20) // 可以监听到变化
        })
    }
    .height('100%')
    .width('100%')
    .padding({ top: 50 })
  }
}

上面这种方式只能通过修改对象整体才能被监听到变化。

如果想通过 this.person.name += '*' 的方式来监听对象中某一个属性的变化,则需要在类上增加 @ObservedV2 装饰器,而且被监听的变量需要添加 @Trace 装饰器:

@ObservedV2
class Person {
  @Trace public name: string;
  public age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

@Monitor('person.name')
dataChange(monitor: IMonitor) {
  monitor.dirty.forEach((path: string) => {
    console.warn(`${path} changed from ${JSON.stringify(monitor.value(path)?.before)} to ${JSON.stringify(monitor.value(path)?.now)}`);
  });
}

此时,就可以监听对象中某一个属性了,效果如下:

【限制条件】不建议在一个类中对同一个属性进行多次@Monitor的监听。当一个类中存在对一个属性的多次监听时,只有最后一个定义的监听方法会生效。具体可参考官方案例:限制条件


示例代码见gitee仓库:V2状态管理

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐