鸿蒙状态管理中V1和V2的区别(3)(HarmonyOS API14版本)

Kratos1023
发布于 2025-3-22 17:44
617浏览
0收藏

上篇文章讲了@Component,@ComponentV2以及@State和@Local的区别。这篇文章就继续讲常用的几个装饰器在V1和V2中的区别。

管理组件拥有状态的装饰器:组件级别的状态管理,可以观察组件内变化,和不同组件层级的变化,但需要唯一观察同一个组件树上,即同一个页面内。

父子传值

V1:@Prop 装饰的变量可以和父组件建立单向的同步关系。装饰的变量是可变的,但是变化不会同步回其父组件。注意:

1.修改父组件数据,会同步更新子组件

2.修改子组件@Prop 修饰的数据,子组件 UI 更新,更新后的数据不会同步给父组件

3.通过回调函数的方式修改父组件的数据,然后触发@Prop数据的更新

V1:@Link 可以实现父组件和子组件的双向同步,当其中一方改变时,另外一方能够感知到变化。

@Component
struct DateComponent {
  @Link selectedDate: Date;
 
  build() {
    Column() {
      Button(`child increase the year by 1`)
      .onClick(() => {
        this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1);
      })
      Button('child update the new date')
        .margin(10)
        .onClick(() => {
          this.selectedDate = new Date('2023-09-09');
        })
      DatePicker({
        start: new Date('1970-1-1'),
        end: new Date('2100-1-1'),
        selected: this.selectedDate
      })
    }
 
  }
}
 
@Entry
@Component
struct ParentComponent {
  @State parentSelectedDate: Date = new Date('2021-08-08');
 
  build() {
    Column() {
      Button('parent increase the month by 1')
        .margin(10)
        .onClick(() => {
          this.parentSelectedDate.setMonth(this.parentSelectedDate.getMonth() + 1);
        })
      Button('parent update the new date')
        .margin(10)
        .onClick(() => {
          this.parentSelectedDate = new Date('2023-07-07');
        })
      DatePicker({
        start: new Date('1970-1-1'),
        end: new Date('2100-1-1'),
        selected: this.parentSelectedDate
      })
 
      DateComponent({ selectedDate:this.parentSelectedDate })
    }
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.

V2:@Param表示组件从外部传入的状态,使得父子组件之间的数据能够进行同步。

@Entry
@ComponentV2
struct Index {
  @Local count: number = 200
  @Local person: Person = new Person('李四', new iToy('奔驰'))
 
  build() {
    Column() {
      Button('修改count值').onClick(() => {
        this.count++
      })
 
      Text(this.person.name)
      Text(this.person.toy.name)
 
      ChildCom({ 
        count: this.count,
      person: this.person
      })
    }
    .height('100%')
    .width('100%')
  }
}
 
@ObservedV2
class Person {
  @Trace name: string
  @Trace toy: iToy
 
  constructor(name: string, toy: iToy) {
    this.name = name
    this.toy = toy
  }
}
 
@ObservedV2
class iToy {
  @Trace name: string;
 
  constructor(name: string) {
    this.name = name
  }
}
 
@ComponentV2
struct ChildCom {
  @Param count: number = 100
  @Param person: Person = new Person('靓仔', new iToy('玩具'))
 
  build() {
    Column() {
      Text(this.count.toString())
      Text(this.person.name)
      Text(this.person.toy.name)
 
 
      Button('修改person.name变量')
        .onClick(() => {
          // 不会更新UI
          this.person.name = '靓仔3'
          // this.person.toy = { name: '玩具3' }
          this.person.toy.name = '玩具3'
        })
 
    }
    .height('100%')
    .width('100%')
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.

注意:

@Param不仅可以接受组件外部输入,还可以接受@Local的同步变化,@Param装饰的变量变化时,会刷新该变量关联的组件。
@Param装饰的变量支持本地初始化,但是不允许在组件内部直接修改变量本身。
@Param装饰的变量在子组件中无法进行修改。但当装饰的变量类型为对象时,在子组件中修改对象中属性是允许的。
对于复杂类型如类对象,@Param会接受数据源的引用。在组件内可以修改类对象中的属性,该修改会同步到数据源。
V2:@Once装饰器仅在变量初始化时接受外部传入值进行初始化,当后续数据源更改时,不会将修改同步给子组件

@Entry
@ComponentV2
struct Index {
  @Local count: number = 200
 
  build() {
    Column() {
      Button('修改count值').onClick(() => {
        // 由于ChildCom中的count使用了@Once修饰,因此修改变量值,不会引起ChildCom组件中的count改变
        this.count++
      })
      Text(this.count.toString())
 
      ChildCom({
        count: this.count
      })
    }
    .height('100%')
    .width('100%')
  }
}
 
 
@ComponentV2
struct ChildCom {
  @Param @Once count: number = 100
 
  build() {
    Column() {
      Text(this.count.toString())
        .onClick(()=>{
          // 由于使用了@Once修饰 ,可以本地修改 @Param变量的值
          this.count++
        })
    }
    .height('100%')
    .width('100%')
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.

注意:

@Once必须搭配@Param使用,单独使用或搭配其他装饰器使用都是不允许的。
@Once与@Param搭配使用时,可以在本地修改@Param变量的值,但不会影响到父组件的状态变量(单独@Param修饰的变量是不允许在本地修改变量值的)

标签
收藏
回复
举报


回复
    相关推荐
    恭喜您,今日已阅读两篇内容,特奖励+2声望, 快来领取吧。