使用V1装饰器,需要使用@Component装饰器装饰组件,而V2需要使用@ComponentV2

V1装饰器
@State:组件自己管理自己的状态,添加@State可让普通变量成为状态变量,变量更新,自动刷新UI。
@Prop:常用于父传子,单向数据流,父组件传递到子组件,不可逆传。
@Prop和@State的区别,父传子也可用@State,但@Prop单向数据流更语义化,而且可以避免组件状态紊乱

@Link:父子双向通信
@ObjectLink/@Observed/@Track:局部刷新UI,性能更好,可用于防止图片闪烁
@Provide/@Consume:虽然官方说是双向通信,但实际上只能从@Provide传值到@Consume,逆向无法传值

V2装饰器
@Local 等价于@State
@Param:父传子,父组件传到子组件,子组件无法修改父组件的值,修改则报错,如果想要修改需要使用@Once + @Param
需要注意:
1.一旦使用once,那么父组件只有在第一次传值给子组件,后续子组件的数据就自己维护了
2.@Param【非@Once】的方式传值,如果子组件通过回调修改了父组件的值,那么这个修改不会同步到子组件
@Require:是否必传
@ObservedV2 + @Tace:可以实现局部刷新,@Tace给需要设置状态变量的属性增加
@Provider() / @Consumer():这一版真正实现了双向通信,功能比V1更强大
@Provider() isScale: boolean = false
@Consumer() isScale: booean = false
其它装饰器
@Event:用来实现父子组件通信的回调函数
// 父组件
getState = (state: string) => { console.log("状态:", state) }

// 父传子
TSMTest({

getState: this.getState

})

// 子组件
@Event getState: (state: string) => void = (state: string) => {}
Watch
V1版本:@Watch
@Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。

装饰器参数:必填。常量字符串,字符串需要有引号。是(string) => void自定义成员函数的方法的引用。

  1. 如果在@Watch的方法里改变了其他的状态变量,也会引起状态变更和@Watch的执行;
  2. 在第一次初始化的时候,@Watch装饰的方法不会被调用,即认为初始化不是状态变量的改变。只有在后续状态改变时,才会调用@Watch回调方法。
  3. 为了避免循环的产生,建议不要在@Watch的回调方法里修改当前装饰的状态变量;
  4. 属性值更新函数会延迟组件的重新渲染,因此,回调函数应仅执行快速运算;

V2版本:@Monitor
@Monitor("isScale")
getShowScale() {

if(this.isScale) {
    console.log("大小恢复")
}

}
@Monitor装饰器具有深度监听的能力,能够监听嵌套类、多维数组、对象数组中指定项的变化。对于嵌套类、对象数组中成员属性变化的监听要求该类被@ObservedV2装饰且该属性被@Trace装饰。

只有状态变量的更新才能触发@Monjtor的回调函数

单个@Monitor装饰器能够同时监听多个属性的变化,当这些属性在一次事件中共同变化时,只会触发一次@Monitor的回调方法。

在继承类场景中,可以在父子组件中对同一个属性分别定义@Monitor进行监听,当属性变化时,父子组件中定义的@Monitor回调均会被调用。

@Monitor支持对数组中的项进行监听,包括多维数组,对象数组。@Monitor无法监听内置类型(Array、Map、Date、Set)的API调用引起的变化。当@Monitor监听数组整体时,只能观测到数组整体的赋值。可以通过监听数组的长度变化来判断数组是否有插入、删除等变化。当前仅支持使用"."的方式表达深层属性、数组项的监听。

在一次事件中多次改变被@Monitor监听的属性,以最后一次修改为准。
Column() {

  Button("change count to 1000")
    .onClick(() => {
      for (let i = 1; i <= 1000; i++) {
        this.frequence.count = i;
      }
    })
  Button("change count to 0 then to 1000")
    .onClick(() => {
      for (let i = 999; i >= 0; i--) {
        this.frequence.count = i;
      }
      this.frequence.count = 1000; // 最终不触发onCountChange方法
    })
}

在点击按钮"change count to 1000"后,会触发一次onCountChange方法,并输出日志"count change from 0 to 1000"。在点击按钮"change count to 0 then to 1000"后,由于事件前后属性count的值并没有改变,都为1000,所以不触发onCountChange方法。

限制
当一个类中存在对一个属性的多次监听时,只有最后一个定义的监听方法会生效。

@Monitor监听的目标属性从初始化时便已经确定,无法动态更改。不建议开发者使用变量作为@Monitor的参数进行初始化。

建议开发者避免在@Monitor中再次更改被监听的属性,这会导致无限循环。

总结:
@Watch只能监听单个状态变量,跟随状态变量观察能力(一层)。
@Monitor能同时监听多个状态变量,跟随状态变量观察能力(深层)【需要@Tace】。
AppStorage
V1版本的AppStorage直接用装饰器就行,@StorageProp + @StorageLink即可,V2的装饰器稍显复杂一些,但好处也更明显,V1装饰器共用一个AppStorage,而V2版装饰器可以实现多个AppStorage
@ObservedV2
class AppStorageKey {

@Tace
isScale: boolean = false
textController: TextController = new TextController()

}

@Local appStorage: AppStorageKey = AppStorageV2.connect(AppStorageKey, () => new AppStorageKey())!

// 使用
this.appStorage.isScale = true
自定义组件混用的场景

  • V1的自定义组件中不可以使用V2的装饰器,否则编译报错。
  • 组件间不存在变量传递时,V1的自定义组件中可以使用V2的自定义组件,包括import第三方@ComponentV2装饰的自定义组件。
  • 组件间存在变量传递时,V1的变量传递给V2的自定义组件,有如下限制:

    • V1中未被装饰器装饰的变量(后称普通变量):V2只能使用@Param接收。
    • V1中被装饰器装饰的变量(后称状态变量):V2存在只能通过@Param装饰器接收,且仅限于boolean、number、enum、string、undefined、null这些简单类型数据。
  • V2的自定义组件中不可以使用V1的装饰器,否则编译报错。
  • 组件间不存在变量传递时,V2自定义组件可以使用V1的自定义组件,包括import第三方@Component装饰的自定义组件。
  • 组件间存在变量传递时,V2的变量传递给V1的自定义组件,有如下限制:

    • V2中未被装饰器装饰的变量(后称普通变量):若V1使用装饰器装饰接收的数据,只能通过@State、@Prop、@Provide。
    • V2中被装饰器装饰的变量(后称状态变量):若V1使用装饰器装饰接收的数据,不支持内置类型数据:Array、Set、Map、Date。
      V1如何迁移到V2装饰器
      https://developer.huawei.com/consumer/cn/doc/harmonyos-guides...

单身的肉夹馍
1 声望0 粉丝