【HarmonyOS 4.0】组件级变量的状态管理

  1. 如果父组件同时去修改子组件所对应的 @State 状态变量时,那么子组件的这俩个 @Prop 状态变量的更新顺序和在子组件的声明顺序是一样的。先声明的先更新,后声明的后更新。

1. @State装饰器 - 组件内状态

  1. 是私有的,只能从组件内部访问。
  2. 在声明时 必须指定其类型和本地初始化。
  3. 与子组件中的 @Prop,@Link、@ObjectLink装饰变量之间建立双向数据同步。
  4. 允许装饰的类型:string、number、boolean、object、class 和 enum类型,以及这些类型的数组。
  5. 并不是@State状态变量的所有更改都会引起UI刷新,只有可以被框架观察到的修改才会引起UI刷新。
  6. 框架能够观察到的变化如下:
    6.1 当@State装饰的变量类型为string、number、boolean类型时,可以观察到赋值的变化。
    6.2 当@State装饰的变量类型为object、class类型时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为 object 或者 class 时,则嵌套属性的变化是观察不到的。
    6.3 当@State装饰的变量类型为数组时,可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为 object 或者 class 时,元素属性的变化是观察不到的。
// 自定义类型
class Person {
  public name: string
  public age: number

  constructor(xName: string, xAge: number) {
    this.name = xName
    this.age = xAge
  }
}
// 自定义子组件
@Component
struct MyChild {
  @State person: Person = new Person('魔鬼', 18) // 指定自定义类型,初始化值
  private increase: number = 1

  build() {
    Column({space: 3}) {
      Text(`${this.person.name}、年龄${this.person.age}`).fontSize(18).fontWeight(500).height(60)
      Divider()
      Button(`修改姓名`).onClick(() => {
        this.person.name = this.person.name ===  '魔鬼' ? '天使': '魔鬼'
      })
        .width(200)
        .height(60)
      Button('修改年龄').onClick(() => {
        this.person.age += this.increase
      })
        .width(200)
        .height(60)
    }
      // .backgroundColor('#CCBBFF')
  }
}
// 父组件
@Entry
@Component
struct UITest5 {
  build() {
    Column({space: 30}) {
      MyChild({person: new Person('天使', 2), increase: 1})
      MyChild({increase: 2})
      MyChild()
    }
  }
}

2. @Prop装饰器 - 父子单向同步

  1. @Prop装饰器不能在@Entry装饰的自定义组件中使用。
  2. 被装饰变量的初始值,允许本地初始化。
  3. 允许装饰的类型:string、number、boolean 和 enum类型,注意不支持 class、object 和数组。
  4. 框架能够观察到的变化如下:
    4.1 当@Prop装饰的类型是允许的类型,所有赋值的变化都可以观察到。
// @Prop装饰器 - 父子单向同步
// 子组件
@Component
struct MyChild {
  @Prop age: number = 9 // 被装饰变量的初始值,允许本地初始化。当没有初始值时,页面显示undefined
  private increase: number = 1
  build() {
    Column(){
      if (this.age >= 18) {
        Text(`子组件年龄${this.age}`).height(60)
      } else {
        Text(`未成年${this.age}`).height(60)
      }
      Button('减少子组件年龄').onClick(() => {
        this.age -= this.increase
      })
    }
  }
}
// 父组件
@Entry
@Component
struct UITest6{
  @State init_age: number = 14
  build() {
    Column() {
      Text(`父组件年龄${this.init_age}`).height(60)
      Button('增加父组件年龄').onClick(() => {
        this.init_age += 1
      })
      Divider()
      MyChild({age: this.init_age, increase: 2})
      Divider()
      MyChild()
    }
  }
}

3. @Link装饰器 - 父子双向同步

  1. 父组件中@State、@StorageLink、@Link 和 子组件@Link可以建立双向数据同步。
  2. 被装饰变量的初始值,禁止本地初始化。
  3. 父组件必须用 $变量名 的方式传参,表示传递的是变量的引用。
  4. 允许装饰的类型:string、number、boolean、object、class 和 enum类型,以及这些类型的数组。(同@State)
  5. 框架能够观察到的变化如下:(同@State)
    5.1 当@State装饰的变量类型为string、number、boolean类型时,可以观察到赋值的变化。
    5.2 当@State装饰的变量类型为object、class类型时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为 object 或者 class 时,则嵌套属性的变化是观察不到的。
    5.3 当@State装饰的变量类型为数组时,可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为 object 或者 class 时,元素属性的变化是观察不到的。

下面代码展示了class类对象类型、简单类型,俩种父子双向数据同步示例。

// @Link装饰器 - 父子双向同步。class类对象类型和简单类型俩种父子双向同步
// 自定义class类对象类型
class ButtonState {
  value: string
  width: number

  constructor(value: string, width: number) {
    this.value = value
    this.width = width
  }
}
// 一号子组件 - class类对象类型
@Component
struct MyChildButton01 {
  // class类对象类型
  @Link buttonState: ButtonState

  build() {
    Column() {
      Button(`${this.buttonState.value}${this.buttonState.width}`)
        .width(this.buttonState.width)
        .height(50)
        .backgroundColor('#B088FF')
        .fontColor('#FFFFFF,90%')
        .onClick(() => {
          if (this.buttonState.width < 400) {
            this.buttonState.width += 50
          } else {
            this.buttonState = new ButtonState('一号本地', 100)
          }
        })
    }
  }
}
// 二号子组件 - 简单类型
@Component
struct MyChildButton02 {
  // 简单类型
  @Link buttonValue: string
  @Link buttonWidth: number

  build() {
    Column() {
      Button(`${this.buttonValue}${this.buttonWidth}`)
        .width(this.buttonWidth)
        .height(50)
        .backgroundColor('#FF7744')
        .fontColor('#FFFFFF,90%')
        .onClick(() => {
          this.buttonValue = this.buttonWidth < 400 ? this.buttonValue : '二号本地'
          this.buttonWidth = this.buttonWidth < 400 ? this.buttonWidth + 50 : 100
        })
    }
  }
}
// 父组件
@Entry
@Component
struct UITest6 {
  // class类对象类型
  @State parentButton: ButtonState = new ButtonState('一号子级', 100)
  // 简单类型
  @State parentValue: string = '二号子级'
  @State parentWidth: number = 100

  build() {
    Column({space: 10}) {
      Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
        // class类对象类型从父组件@State向子组件@Link数据同步
        Button(`父组件中修改${this.parentButton.value}${this.parentButton.width}`).onClick(() => {
          this.parentButton.width = this.parentButton.width < 400 ? this.parentButton.width + 50 : 100
        })
        // 简单类型从父组件@State向子组件@Link数据同步
        Button(`父组件中修改${this.parentValue}${this.parentWidth}`).onClick(() => {
          this.parentWidth = this.parentWidth < 400 ? this.parentWidth + 50 : 100
        })
        // class类对象类型初始化@Link
        MyChildButton01({ buttonState: $parentButton })
        // 简单类型初始化@Link
        MyChildButton02({ buttonValue: $parentValue, buttonWidth: $parentWidth })
      }
    }
  }
}

4. @Provide装饰器、@Consume装饰器 - 与后代组件双向同步

  1. 用于跨组件层级传递状态信息,其中 @Provide 用于装饰祖先组件的状态变量, @Consume 用于装饰后代组件的状态变量。并且状态信息可以实现双向同步。
  2. @Provide装饰的变量必须进行本地初始化;@Consume装饰的变量不允许进行本地初始化。
  3. @Provide 和 @Consume 装饰的变量不是通过父组件向子组件传参的方式进行绑定的,而是通过相同的变量名进行绑定的。
  4. 除了通过变量名进行绑定,还可通过变量的别名进行绑定。
    在这里插入图片描述
  5. 允许装饰的类型:string、number、boolean、object、class 和 enum类型,以及这些类型的数组。(同@State)
  6. 框架能够观察到的变化如下:(同@State)
    6.1 当@State装饰的变量类型为string、number、boolean类型时,可以观察到赋值的变化。
    6.2 当@State装饰的变量类型为object、class类型时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为 object 或者 class 时,则嵌套属性的变化是观察不到的。
    6.3 当@State装饰的变量类型为数组时,可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为 object 或者 class 时,元素属性的变化是观察不到的。

5. @Observed装饰器、@ObjectLink装饰器 - 嵌套类对象属性变化

  1. @Observed装饰器 装饰类型的定义
  2. @ObjectLink装饰器 装饰状态变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值