鸿蒙Harmony--状态管理器--@State详解

山海自有归期,风雨自有相逢!山鸟与鱼是不会同路的。勿在他人心中修行自己,勿在自己心中强求别人。往前走吧,风雨扑面乃是人生常态,聚散离合也不稀奇。吃咸一点看淡一点,毕竟一百年以后没有你也没有我!

目录

一,定义

二,@State装饰器

1,定义

2,装饰器使用规则说明

3,变量的传递/访问规则说明

4,使用

①简单使用

②当装饰的数据类型为class或者Object时,可以观察到自身的赋值的变化,和其属性赋值的变化

③当装饰的对象是array时,可以观察到数组本身的赋值和添加、删除、更新数组的变化

④多组件内部值的传递

一,定义

在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。

自定义组件拥有变量,变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起UI的渲染刷新。如果不使用状态变量,UI只能在初始化时渲染,后续将不会再刷新。

状态变量:被状态装饰器装饰的变量,状态变量值的改变会引起UI的渲染更新。示例:@State num: number = 1,其中,@State是状态装饰器,num是状态变量。

常规变量:常规变量:没有被状态装饰器装饰的变量,通常应用于辅助计算。它的改变永远不会引起UI的刷新。

数据源/同步源:数据源/同步源:状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。

命名参数机制:父组件通过指定参数传递给子组件的状态变量,为父子传递同步参数的主要手段。示例:CompA: ({ aProp: this.aProp })。

从父组件初始化:父组件使用命名参数机制,将指定参数传递给子组件。子组件初始化的默认值在有父组件传值的情况下,会被覆盖。

初始化子节点:父组件中状态变量可以传递给子组件,初始化子组件对应的状态变量。

本地初始化:在变量声明的时候赋值,作为变量的默认值。示例:@State count: number = 0。

二,@State装饰器

1,定义

@State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI会发生对应的渲染改变。

在状态变量相关装饰器中,@State是最基础的,使变量拥有状态属性的装饰器,它也是大部分状态变量的数据源。

@State装饰的变量,与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化。初始化也可选择使用命名参数机制从父组件完成初始化。

@State装饰的变量拥有以下特点:

①@State装饰的变量与子组件中的@Prop装饰变量之间建立单向数据同步,与@Link、 @ObjectLink装饰变量之间建立双向数据同步。

②@State装饰的变量生命周期与其所属自定义组件的生命周期相同。

2,装饰器使用规则说明

@State变量装饰器 说明
装饰器参数
同步类型 不与父组件中任何类型的变量同步。
允许装饰的变量类型 Object、class、string、number、boolean、enum类型,以及这些类型的数组。 支持Date类型。 支持类型的场景请参考观察变化。 类型必须被指定。 不支持any,不支持简单类型和复杂类型的联合类型,不允许使用undefined和null。 说明: 不支持Length、ResourceStr、ResourceColor类型,Length、ResourceStr、ResourceColor为简单类型和复杂类型的联合类型。
被装饰变量的初始值 必须本地初始化。

3,变量的传递/访问规则说明

传递/访问 说明
从父组件初始化 可选,从父组件初始化或者本地初始化。如果从父组件初始化将会覆盖本地初始化。 支持父组件中常规变量(常规变量对@State赋值,只是数值的初始化,常规变量的变化不会触发UI刷新,只有状态变量才能触发UI刷新)、@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp装饰的变量,初始化子组件的@State。
用于初始化子组件 @State装饰的变量支持初始化子组件的常规变量、@State、@Link、@Prop、@Provide。
是否支持组件外访问 不支持,只能在组件内访问。

4,使用

①简单使用

TypeScript 复制代码
@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.message = '修改后'
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

点击后

②当装饰的数据类型为class或者Object时,可以观察到自身的赋值的变化,和其属性赋值的变化

定义两个数据类:

TypeScript 复制代码
export default class YuanZhen {

  public name: string = 'YuanZhen';

  public age: number = 18;

  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }
}
TypeScript 复制代码
import YuanZhen from './YuanZhen';

export default class Yuan {

  public number: number = 1;
  public yuanZhen: YuanZhen = new YuanZhen('yuanzhen', 18);

  constructor(number: number, yuanZhen: YuanZhen) {
    this.number = number
    this.yuanZhen = yuanZhen
  }
}

使用:

TypeScript 复制代码
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State yuan:Yuan =new Yuan(1,new YuanZhen("yuanzhen",18))

  build() {
    Row() {
      Column() {
        Text("number:"+this.yuan.number+"\nName:"+this.yuan.yuanZhen.name+"\nAge:"+this.yuan.yuanZhen.age)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.yuan.number++
            this.yuan.yuanZhen.name="袁震"+this.yuan.number
            this.yuan.yuanZhen.age++
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

点击后继续点击

可以看到,对于嵌套属性,其值改变,同样可以观察的到

③当装饰的对象是array时,可以观察到数组本身的赋值和添加、删除、更新数组的变化

代码如下:

TypeScript 复制代码
import YuanZhen from './bean/YuanZhen';

@Entry
@Component
struct Index {
  @State yuanArray:Array<YuanZhen> =new Array<YuanZhen>();

  aboutToAppear(){
    this.yuanArray.push(new YuanZhen("袁震",18))
  }

  build() {
    Row() {
      Column() {
        Text("数组长度:"+this.yuanArray.length+"\n最后一个值:"+this.yuanArray[this.yuanArray.length-1].age)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{

          })
        Button("增加").onClick(()=>{
          this.yuanArray.push(new YuanZhen("袁震",18+this.yuanArray.length))
        })
        Button("删除").onClick(()=>{
          this.yuanArray.pop()
        })
        Button("赋值").onClick(()=>{
          this.yuanArray[this.yuanArray.length-1].age=100
        })
      }
      .width('100%')
    }
    .height('100%')
  }
}

点击增加时:

再点击增加

点击删除时:

点击赋值时没有反应,所以数组项中属性的赋值观察不到。

④多组件内部值的传递

如果有一个自定义组件:

TypeScript 复制代码
import YuanZhen from './bean/YuanZhen'

@Component
export default struct YzComponent {
  @State yuanZhen:YuanZhen=new YuanZhen("袁震",18)

  build() {
    Row() {
      Column() {
        Text("name:"+this.yuanZhen.name+"\nage:"+this.yuanZhen.age)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)

      }
      .width('100%')
    }
    .height('100%')
  }
}

在使用时传入一个默认值:

TypeScript 复制代码
import YuanZhen from './bean/YuanZhen';
import YzComponent from './YzComponent'

@Entry
@Component
struct Index {
  @State yuanZhen:YuanZhen =new YuanZhen("袁世震",22)

  build() {
    Column(){
      YzComponent({yuanZhen:this.yuanZhen})
    }
  }
}

运行效果:

对于@State来说,命名参数机制传递的值并不是必选的,如果没有命名参数传值,则使用本地初始化的默认值 ,有命名参数传递,就使用传递的值

相关推荐
一只栖枝7 小时前
华为 HCIE 大数据认证中 Linux 命令行的运用及价值
大数据·linux·运维·华为·华为认证·hcie·it
zhanshuo11 小时前
在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
harmonyos
zhanshuo11 小时前
在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
harmonyos
whysqwhw17 小时前
鸿蒙分布式投屏
harmonyos
whysqwhw18 小时前
鸿蒙AVSession Kit
harmonyos
whysqwhw20 小时前
鸿蒙各种生命周期
harmonyos
whysqwhw21 小时前
鸿蒙音频编码
harmonyos
whysqwhw21 小时前
鸿蒙音频解码
harmonyos
whysqwhw21 小时前
鸿蒙视频解码
harmonyos
whysqwhw21 小时前
鸿蒙视频编码
harmonyos