状态管理@State

       

目录

一、简单类型的更新

二、class对象类型的变量


        被该装饰器修饰的变量,在数据变化时会触发UI的刷新,也就是ArkTS UI中触发build()函数的调用,重新根据状态构建UI。如下更新是可以观察到的:

        1、string number boolean 类型的数据可以被监听到更新

        2、class类型 可以观察到自身的赋值的变化,和其属性赋值的变化(嵌套属性的赋值观察不到。)

一、简单类型的更新

@Entry
@Component
struct MyComponent {
  @State count: number = 0;

  build() {
    Button(`click times: ${this.count}`)
      .onClick(() => {
        this.count += 1;
      })
  }
}

        按钮Button绑定了一个点击事件,当点击事件发生时,@State修饰的变量count会加1,框架检测到状态变更,然后查询依赖该变量的组件,执行依赖该状态变量的组件的更新方法,组件更新渲染,而和该状态变量不相关的组件或者UI描述不会发生重新渲染,从而实现页面渲染的按需更新。

二、class对象类型的变量

@Entry
@Component
struct StateDemoPage {
  private flag: boolean = true;
  //string number boolean 类型的数据可以被监听到更新
  @State index: number = 0
  // class类型 可以观察到自身的赋值的变化,和其属性赋值的变化
  @State title: Model = new Model('Hello', new ClassA('World'));
  /**
   * 1 数组自身的赋值可以观察到。
   * 2 数组项的赋值可以观察到。
   * 3 删除数组项可以观察到。
   * 4 新增数组项可以观察到。
   * 5 数组项中属性的赋值观察不到。(X)
   */
  @State array: Model[] = [new Model('a', new ClassA('xx')), new Model('b', new ClassA('yy'))]

  build() {
    Row() {
      Column({ space: 12 }) {
        Text(`${this.index}`).stateTextStyle(() => {
          this.index++
        })

        Text(`${this.title.key}-${this.title.value.subtitle}`).stateTextStyle(() => {
          if (this.flag) {
            this.title = new Model('World', new ClassA('Hello'))
          } else {
            this.title.key = 'World Change'
          }
          this.flag = !this.flag
          // 嵌套的属性赋值观察不到
          // this.title.name.value = 'ArkUI'
        })

        ForEach(this.array, (item: Model, index) => {
          Row() {
            Text(item.key).width('40%').fontSize(24).backgroundColor(Color.Orange)
            Text(item.value.subtitle).width('40%').fontSize(24).fontColor(Color.Red).backgroundColor(Color.Blue)
          }.backgroundColor('#8067c8ff').transition({ type: TransitionType.All, translate: {x: 200, y: 40} })
        }, item => JSON.stringify(item))

        Button('ClickMe')
          .backgroundColor('#67c8ff')
          .fontColor(Color.White)
          .borderRadius(12)
          .height(44)
          .padding({ left: 24, right: 24 })
          .onClick(() => {
            animateTo({}, () => {
              // this.array = [new Model('dd', new ClassA('zz')), new Model('mm', new ClassA('z1z1'))]
              // this.array[0] = new Model('AA', new ClassA('xx'))
              // this.array.unshift(new Model('AA', new ClassA('xx'))) //头部插入
              // this.array.shift()//头部删除
              // this.array.push(new Model('AA', new ClassA('xx'))) //尾部插入
              // this.array.pop()//尾部删除

              //元素中属性的赋值不能被观察到[所与可被观察到的属性一起使用的话,也可以被观察到]
              this.array[0].value.subtitle = 'Nested action'
            })
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}



export class ClassA {
  public subtitle: string;

  constructor(value: string) {
    this.subtitle = value;
  }
}

export class Model {
  public key: string;
  public value: ClassA;
  constructor(key: string, value: ClassA) {
    this.key = key;
    this.value = value;
  }
}

        上例中演示了以下几种情况:

  • 数组自身的赋值可以观察到。
this.array = [new Model('dd', new ClassA('zz')), new Model('mm', new ClassA('z1z1'))]
  • 数组项的赋值可以观察到。
this.array[0] = new Model('AA', new ClassA('xx'))
  • 删除数组项可以观察到。
this.array.shift()//头部删除
this.array.pop()//尾部删除
  • 新增数组项可以观察到。
this.array.unshift(new Model('AA', new ClassA('xx'))) //头部插入
this.array.push(new Model('AA', new ClassA('xx'))) //尾部插入
  • 数组项中属性的赋值观察不到。(X)

        此情况需要说明下,如果单独像下面这样更新数据时,框架是不是检测到数据变化的,也就不会触发UI刷新:

this.array[0].value.subtitle = 'Nested action'

        但是但是但是当与其他可被观察到的行为一起更新数据时,也是能正确刷新的到UI上的呢(个人猜想:可被观察的行为能触发UI更新,UI更新时会把相关联的数据都用上,所以能更新到UI上)。

你可能感兴趣的:(鸿蒙4.0开发,harmonyos)