状态管理简介

ArkUI 开发提供了多维度的状态管理机制。状态管理机制能使父子组件之间,爷孙组件之间数值传递,还可以跨设备传递。从数据的传递形式看,可以分为只读的单向传递和可变更的双向传递。与vue的用法特别像。

@State修饰符

@State有以下特征:

  1. 支持多种数据类型: class number boolean string 强类型的值和引用类型。允许强类型构成的数组:Array< class >、Array< string >、Array< boolean >、Array< number >。不允许object和any
  2. 内部私有: 标记为@State的属性,表明当前变量为私有变量,只能当前组件内访问。
  3. 支持多个实例: 组件不同实例的内部状态数据独立
  4. 本地初始化: 必须为所有 @State 变量分配初始值

案例:

@Entry
@Component
export struct stateData{
  @State title:string = "迪加奥特曼"
  build(){
    Column(){
      Text(this.title).fontSize(36)
      Divider().margin({top:50,bottom:50})
      Button("修改标题").onClick(()=>{
        this.title = "迪迦奥特曼他爹"
      })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

@Prop修饰符

@Prop与@State有相同语义,但是初始方式不同,用法也不同。@Prop用在父组件内。父组件能改变子组件使用@Prop装饰的数据。反观,子组件的更改不影响父组件。
@Prop有以下特征:

  1. 内部私有: 标记为@Prop的属性,表明当前变量为私有变量,只能当前组件内访问。
  2. 支持简单数据类型: 支持number,string,boolean类型。
  3. 支持多个实例: 组件不同实例的内部状态数据独立。
  4. 不支持内部初始化: 在创建组件的新实例时,必须将值传递给 @Prop 修饰的变量进行初始化,不支持在组件内部进行初始化。

案例:

@Entry
@Component
export struct propData{
  @State title:string = "迪加奥特曼"
  build(){
    Column(){
      childCpn({ childData:this.title })// 必须初始化子组件的childData字段

      Divider().margin({top:10,bottom:10})

      Text("父组件:"+this.title).fontSize(36)

      Divider().margin({top:50,bottom:50})
      Button("修改标题").onClick(()=>{
        this.title = "迪迦奥特曼他爹"// 父组件的更改影响子组件
      })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

@Component
struct childCpn{
  @Prop childData:string; // 不允许本地初始化
  build(){
    Text(this.childData).fontSize(36).onClick(()=>{
      this.childData = "泰罗奥特曼" // 子组件的更改不影响父组件
    })

  }
}

@Link修饰符

@Link与@State有相同语义。@Link装饰的变量能和父组件的@State装饰的变量建立双休的数据绑定。
@Link有以下特征:

  1. 内部私有: 标记为@Link的属性,表明当前变量为私有变量,只能当前组件内访问。
  2. 支持多种数据类型: 支持class,number,string,boolean或者这些类型的数据。
  3. 支持多个实例: 组件不同实例的内部状态数据独立。
  4. 不支持内部初始化: 在创建组件的新实例时,必须将值传递给 @Link 修饰的变量进行初始化,不支持在组件内部进行初始化。初始化使用 $ 符号,例如:$data。

案例:

@Entry
@Component
export struct propData{
  @State title:string = "迪加奥特曼"
  build(){
    Column(){
      childCpn({ childData:$title })// 必须初始化子组件的childData字段

      Divider().margin({top:10,bottom:10})

      Text("父组件:"+this.title).fontSize(36)

      Divider().margin({top:50,bottom:50})
      Button("修改标题").onClick(()=>{
        this.title = "迪迦奥特曼他爹"// 父组件的更改影响子组件
      })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

@Component
struct childCpn{
  @Link childData:string; // 不允许本地初始化
  build(){
    Text(this.childData).fontSize(36).onClick(()=>{
      this.childData = "泰罗奥特曼" // 子组件的更改不影响父组件
    })

  }
}

@StorageLink修饰符

@Link与@State有相同语义。@Link装饰的变量能和父组件的@State装饰的变量建立双休的数据绑定。
@Link有以下特征:

  1. 本地初始化: @StorageLink装饰的变量分配初始值。
  2. 支持多种数据类型: 支持与@State一样的数据类型,同时支持object。
  3. 数据状态全局化: @StorageLink装饰的数据变化后全局都会改变
  4. 数据持久化: 通过搭配 PersistentStorage 接口实现数据持久化

绑定数据

@Entry
@Component
export struct storageLink{
  @StorageLink('date1') data:string = "第一个案例:绑定数据"
  build(){
    Column(){
      Text("随机数:"+this.data).fontSize(36)
      Divider().margin({top:50,bottom:50})
      Button("修改标题").onClick(()=>{
        this.data = Math.random()+""
      })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

双向绑定数据

@Entry
@Component
export struct storageLink{
  @StorageLink('date2') data:string = "第二个案例:双向绑定数据"
  build(){
    Column(){
      Text("随机数:"+this.data).fontSize(36).fontColor(Color.Red).margin({bottom:10})
      CustomCpn()
      Divider().margin({top:50,bottom:50})
      Button("修改标题").onClick(()=>{
        this.data = Math.random()+""
      })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

@Component
struct CustomCpn {
  @StorageLink('date2') time: string = "自定义组件";

  build() {
    Text(`子组件【${this.time}`)
      .fontColor(Color.Blue)
      .fontSize(20)
      .onClick(() => {
        this.time = Math.random()+""
      })
  }
}

页面间数据绑定
页面一

import router from '@ohos.router';
@Entry
@Component
export struct storageLink{
  @StorageLink('date3') data:string = "第三个案例:页面间数据绑定";//tips的值以'key'第一次出现的为准
  build(){
    Column(){
      Text("随机数:"+this.data).fontSize(36).margin({bottom:20})
      CustomCpn()
      Divider().margin({top:50,bottom:50})
      Button("修改数据").onClick(()=>{
        this.data = Math.random()+""
      })
      Button('跨页面数据绑定')
        .onClick(() => {
          router.pushUrl({url: "pages/home/arkTsIntro/stateManage/storageLink/demo3/Two"})// 打开第二个页面
        })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

@Component
struct CustomCpn {
  @StorageLink('date3') time: string = "自定义组件";
  build() {
    Text(`子组件【${this.time}`)
      .fontColor(Color.Blue)
      .fontSize(20)
      .onClick(() => {
        this.time = Math.random()+""
      })
  }
}

页面二

@Entry
@Component
export struct storageLink2{
  @StorageLink('date3') data:string = "案例三,第二个页面";//tips的值以'key'第一次出现的为准
  build(){
    Column(){
      Text("随机数:"+this.data).fontSize(36)
      Divider().margin({top:50,bottom:50})
      Button("修改数据").onClick(()=>{
        this.data = Math.random()+""
      }).margin({bottom:20})
      Button("返回上一页").onClick(()=>{
        router.back()
      })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

持久化数据

// 持久化存储key并设置默认值
PersistentStorage.PersistProp("date4", "持久化数据")
//持久化数据
@Entry
@Component
export struct storageLink{
  @StorageLink('date4') data:string = "第四个案例:持久化数据"
  build(){
    Column(){
      Text("随机数:"+this.data).fontSize(36)
      Divider().margin({top:50,bottom:50})
      Button("修改标题").onClick(()=>{
        this.data = Math.random()+""
      }).margin({bottom:20})
      Button('跨页面数据绑定')
        .onClick(() => {
          router.pushUrl({url: "pages/home/arkTsIntro/stateManage/storageLink/demo3/Two"})// 打开第二个页面
        })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

@Watch修饰符

@Watch用于监听被Watch装饰的变量值变化,当他数值发生更改,会触发相应的方法(funcName)。

@Entry
@Component
export struct watchData{
  @State @Watch("funcName") num:number = 0
  @State title:string = "@Watch装饰变量"

  funcName(){
    this.title = "我发生改变啦"+Math.random()*100;
  }
  build(){
    Column(){
      Text("标题:"+this.title).fontSize(26).margin({bottom:10})
      Text("数值:"+this.num).fontSize(26)

      Divider().margin({top:50,bottom:50})
      Button("修改标题").onClick(()=>{
       this.num++;
      })
    }.alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height("100%")
  }
}

注意:@Watch装饰器只能监听 @State 、 @Prop 、 @Link 、 @ObjectLink 、 @Provide 、 @Consume 、 @StorageProp 以及 @StorageLink 装饰的变量

02-15 12:51