鸿蒙UI开发快速入门 —— part07:组件状态管理之@Prop/@Link装饰器

1、前言

我们在上一章学习了@State装饰器,@State装饰器的作用范围仅仅在当前组件,接下来,我们讨论如何从父组件中传入参数到子组件,让子组件随着父组件的状态发生变化。本章将要介绍的就是:@Props装饰器。

2、@Props装饰器

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

  • @Prop变量允许在本地修改和初始化,但修改后的变化不会同步回父组件。

  • 当父组件中的数据源更改时,与之相关的@Prop装饰的变量都会自动更新。如果子组件已经在本地修改了@Prop装饰的相关变量值,而在父组件中对应的@State装饰的变量被修改后,子组件本地修改的@Prop装饰的相关变量值将被覆盖。

  • @Prop装饰器不能在@Entry装饰的自定义组件中使用。

  • 装饰器允许装饰的变量类型有:string、number、boolean、enum类型。不支持any,不允许使用undefined和null。

  • 装饰的变量必须指定类型,在父组件中,传递给@Prop装饰的值不能为undefined或者null;

  • @Prop装饰的变量和父组件状态变量类型相同,即@Prop : S和@State : S

  • 虽然说@Props装饰的变量可由父组件初始化,但使用范围依旧只能在组件内访问。

核心代码结构如下:

@Componentstruct Child { // 子组件中的@Props变量,可以被父组件初始化  @Prop count: number;}@Entrystruct Parent {  @State parentCount:number = 1;  build() {  // 此时,父组件就将本地parentCount变量传递给了子组件  // 当parentCount发生变化时,子组件也会刷新  Child({count: this.parentCount});  }}

3、@Props装饰器的简单使用Demo

以下示例是@State到子组件@Prop简单数据同步,

父组件ParentComponent的状态变量countDownStartValue初始化子组件CountDownComponent中@Prop装饰的count,

点击“Try again”,count的修改仅保留在CountDownComponent,不会同步给父组件ParentComponent。

ParentComponent的状态变量countDownStartValue的变化将重置CountDownComponent的count。

@Componentstruct CountDownComponent {  @Prop count: number;  costOfOneAttempt: number = 1;  build() {    Column() {      if (this.count > 0) {        Text(`You have ${this.count} Nuggets left`)      } else {        Text('Game over!')      }      // @Prop装饰的变量不会同步给父组件      Button(`Try again`).onClick(() => {        this.count -= this.costOfOneAttempt;      })    }  }}@Entry@Componentstruct ParentComponent {  @State countDownStartValue: number = 10;  build() {    Column() {      Text(`Grant ${this.countDownStartValue} nuggets to play.`)      // 父组件的数据源的修改会同步给子组件      Button(`+1 - Nuggets in New Game`).onClick(() => {        this.countDownStartValue += 1;      })      // 父组件的修改会同步给子组件      Button(`-1  - Nuggets in New Game`).onClick(() => {        this.countDownStartValue -= 1;      })      CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2 })    }  }}

在上面的示例中:

  1. CountDownComponent子组件首次创建时其@Prop装饰的count变量将从父组件@State装饰的countDownStartValue变量初始化,界面如下:

    图片

  2. 按“+1”或“-1”按钮时,父组件的@State装饰的countDownStartValue值会变化,这将触发父组件重新渲染,在父组件重新渲染过程中会刷新使用countDownStartValue状态变量的UI组件并单向同步更新CountDownComponent子组件中的count值;

    图片

  3. 更新count状态变量值也会触发CountDownComponent的重新渲染,在重新渲染过程中,评估使用count状态变量的if语句条件(this.count > 0),并执行true分支中的使用count状态变量的UI组件相关描述来更新Text组件的UI显示;

  4. 当按下子组件CountDownComponent的“Try again”按钮时,其@Prop变量count将被更改,但是count值的更改不会影响父组件的countDownStartValue值;

    图片

  5. 父组件的countDownStartValue值会变化时,父组件的修改将覆盖掉子组件CountDownComponent中count本地的修改。

图片

由于有@State装饰器的经验,学习@Props起来就得心应手了。到此,我们基本也就掌握了@Props装饰器的使用了。

趁热打铁,我们可能就会问了,@Props组件只能由父组件到子组件单向传递,那我想实现双向传递怎么办呢?那就需要用到@Link装饰器了。

4、@Link装饰器

@Link装饰器与@Props装饰器的用法几乎一样,区别只是@Props装饰器是父组件向子组件单向同步,而@Link装饰器是子组件和父组件双向同步。

我们平时使用@Link装饰器就和@Props差不多,有一个区别:@Link装饰器的属性不能本地初始化。

直接上一段Demo:

点击父组件ShufflingContainer中的“Parent View: Set yellowButton” 和 “Parent View: Set GreenButton”,可以从父组件将变化(控件长度)同步给子组件。

1.点击子组件GreenButton和YellowButton中的Button,子组件会发生相应变化,将变化同步回父组件。因为@Link是双向同步,会将变化同步给@State。

2.当点击父组件ShufflingContainer中的Button时,@State变化,也会同步给@Link,子组件也会发生对应的刷新。

图片

代码如下:​​​​​​​

class GreenButtonState {  width: number = 0;  constructor(width: number) {    this.width = width;  }}@Componentstruct GreenButton {  @Link greenButtonState: GreenButtonState;  build() {    Button('Green Button')      .width(this.greenButtonState.width)      .height(40)      .backgroundColor('#64bb5c')      .fontColor('#FFFFFF,90%')      .onClick(() => {        if (this.greenButtonState.width < 700) {          // 更新class的属性,变化可以被观察到同步回父组件          this.greenButtonState.width += 60;        } else {          // 更新class,变化可以被观察到同步回父组件          this.greenButtonState = new GreenButtonState(180);        }      })  }}@Componentstruct YellowButton {  @Link yellowButtonState: number;  build() {    Button('Yellow Button')      .width(this.yellowButtonState)      .height(40)      .backgroundColor('#f7ce00')      .fontColor('#FFFFFF,90%')      .onClick(() => {        // 子组件的简单类型可以同步回父组件        this.yellowButtonState += 40.0;      })  }}@Entry@Componentstruct ShufflingContainer {  @State greenButtonState: GreenButtonState = new GreenButtonState(180);  @State yellowButtonProp: number = 180;  build() {    Column() {      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {        // 简单类型从父组件@State向子组件@Link数据同步        Button('Parent View: Set yellowButton')          .width(312)          .height(40)          .margin(12)          .fontColor('#FFFFFF,90%')          .onClick(() => {            this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 40 : 100;          })        // class类型从父组件@State向子组件@Link数据同步        Button('Parent View: Set GreenButton')          .width(312)          .height(40)          .margin(12)          .fontColor('#FFFFFF,90%')          .onClick(() => {            this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100;          })        // class类型初始化@Link        GreenButton({ greenButtonState: $greenButtonState }).margin(12)        // 简单类型初始化@Link        YellowButton({ yellowButtonState: $yellowButtonProp }).margin(12)      }    }  }}

5、结语

至此,我们在@State装饰器的基础上又学习了@Props装饰器和@Link装饰器,@Props装饰器用于接受来自父组件的变量,@Link也用于接受来自父组件的变量,但额外的,@Link装饰器在子组件中被修改后,父组件中对应的值也会发生改变。

剩下的状态装饰器请持续关注 “鸿蒙UI开发快速入门 —— part08 ”

如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!

扫描下面的二维码关注公众号。

图片

  • 35
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值