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

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

1.1 定义

@State装饰的变量,或者称为状态变量 ,一旦变量拥有了状态属性,就可以触发其直接绑定UI组件的刷新 。当状态改变时,UI会发生对应的渲染变化 ,@State装饰的变量,与声明式范式中的其他被装饰变量一样,是私有 的,只能从组件内部访问。在声明时候必须本地初始化

1.1.1 案例演示

  1. 代码示意
ts 复制代码
import { promptAction } from '@kit.ArkUI'

@Entry
@Component
struct Test {

  num: number = 1

  build() {
    Column() {
      Row({space:20}) {
        Button('+')
          .onClick(()=>{
            this.num++
            promptAction.showToast({
              message:this.num+''
            })
          })
        Text(this.num + '')
        Button('-')
          .onClick(()=>{
            this.num--
            promptAction.showToast({
              message:this.num+''
            })
          })
      }
    }.width('100%')
    .height('100%')
  }
}
  1. 演示

如下图显示,点击Button按钮,UI界面并不会更新,但是我们通过弹层提示是可以明显看到数据变化了的,

  1. 加上@State装饰器后的正确效果

    import { promptAction } from '@kit.ArkUI'

    @Entry
    @Component
    struct Test {
    @State
    num: number = 1

    build() {
    Column() {
    Row({space:20}) {
    Button('+')
    .onClick(()=>{
    this.num++
    promptAction.showToast({
    message:this.num+''
    })
    })
    Text(this.num + '')
    Button('-')
    .onClick(()=>{
    this.num--
    promptAction.showToast({
    message:this.num+''
    })
    })
    }
    }.width('100%')
    .height('100%')
    }
    }

通过上述案例,我们可以得出结论,@State装饰器修饰的数据变化可以让UI发生变化,但是在鸿蒙中,@State装饰器也有限制。在修饰引用数据的时候,@State装饰器只能监测对象自身和第一层的变化

1.2@State装饰器的限制以及解决办法

1.2.1限制

@State修饰引用类型的数据时候,只能在自身或者第一层发生变化的时候产生更新

  1. 案例
ts 复制代码
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct Test01 {
  //1.数据驱动UI变化  加上@State装饰器
  @State
  persionInfo: PersionInfo = {
    name: '小程',
    age: '21',
    sex: '女',
    address: {
      province: '安徽',
      city: '黄山市',
      area: '黄山'
    }
  }

  build() {
    Column() {
      Row() {
        Text('姓名:')
        TextInput({ text: this.persionInfo.name })
          .layoutWeight(1)
      }.width('100%')
      .padding(20)

      Row() {
        Text('年龄:')
        TextInput({ text: this.persionInfo.age })
          .layoutWeight(1)
      }.width('100%')
      .padding(20)

      Row() {
        Text('性别:')
        TextInput({ text: this.persionInfo.sex })
          .layoutWeight(1)
      }.width('100%')
      .padding(20)

      Row({ space: 10 }) {
        Text('地址:')
        TextInput({ text: this.persionInfo.address.province })
          .layoutWeight(1)
        TextInput({ text: this.persionInfo.address.city })
          .layoutWeight(1)
        TextInput({ text: this.persionInfo.address.area })
          .layoutWeight(1)
      }.width('100%')
      .padding(20)

      Row({ space: 20 }) {
        Button('改变姓名')
          .onClick(() => {
            this.persionInfo.name = '小程神'
          })
        Button('改变省份')
          .onClick(() => {
            this.persionInfo.address.province = '河北'
            promptAction.showToast({
              message: JSON.stringify(this.persionInfo.address)
            })
          })
      }
    }.width('100%')
    .height('100%')
  }
}

interface Address {
  province: string
  city: string
  area: string
}

interface PersionInfo {
  name: string
  age: string
  sex: '男' | '女'
  address: Address
}
  1. 效果展示
  1. 案例分析
  • 在我们修改姓名的时候,姓名也是成功修改,但是我们在修改省份的时候,却没有成功修改,但是数据其实更改的了,但是UI层并没有更新,这就涉及到了鸿蒙里面@State装饰器修饰的引用数据只能修改本身或者第一层数据,而省份是在address里面的第二层,所以自然不会刷新,所以通过修改自身和第一层我们可以更新省份

1.2.2解决方法

  1. 方法一:修改第一层
  • 代码
ts 复制代码
 Button('改变省份')
          .onClick(() => {
            this.persionInfo.address = {
              province:'河北',
              city:'保定',
              area:'莲池区'
            }
            promptAction.showToast({
              message: JSON.stringify(this.persionInfo.address)
            })
          })
  • 效果展示

2.方法二:修改自身

  • 代码演示
ts 复制代码
     Button('改变省份')
          .onClick(() => {
            // this.persionInfo.address = {
            //   province:'河北',
            //   city:'保定',
            //   area:'莲池区'
            // }
            this.persionInfo={
              name: '小程',
              age: '21',
              sex: '女',
              address: {
                province: '河北',
                city: '黄山市',
                area: '黄山'
              }

            }
            promptAction.showToast({
              message: JSON.stringify(this.persionInfo.address)
            })
          })
  • 效果展示

通过上述方法,我们可以总结为UI更新的原理就是产生了一个新对象,得到一个新对象,UI就会更新,另辟蹊径,我们可以把接口转换为类,然后new一个对象去赋值,然后更新UI

  1. 方法三:new 一个新对象
  • 代码展示
ts 复制代码
export class AddressModel implements Address {
  province: string = ''
  city: string = ''
  area: string = ''

  constructor(model: Address) {
    this.province = model.province
    this.city = model.city
    this.area = model.area
  }
}
export class PersionInfoModel implements PersionInfo {
  name: string = ''
  age: string = ''
  sex: '男' | '女' = '男'
  address: Address = new AddressModel({} as Address)

  constructor(model: PersionInfo) {
    this.name = model.name
    this.age = model.age
    this.sex = model.sex
    this.address = model.address
  }
}
    Button('改变省份')
          .onClick(() => {
            // this.persionInfo.address = {
            //   province:'河北',
            //   city:'保定',
            //   area:'莲池区'
            // }
            // this.persionInfo={
            //   name: '小程',
            //   age: '21',
            //   sex: '女',
            //   address: {
            //     province: '河北',
            //     city: '黄山市',
            //     area: '黄山'
            //   }
            //
            // }
            this.persionInfo.address.province = '四川'
            this.persionInfo = new PersionInfoModel(this.persionInfo)
            promptAction.showToast({
              message: JSON.stringify(this.persionInfo.address)
            })
  • 效果展示

1.3总结

  1. @State装饰器可以通过数据驱动视图更新
  2. 在鸿蒙中,@State只能监听到引用数据的本身和第一层,不能监听到第二层
  3. 如果想监听到第二层以及第二层往后,可以改变数据的本身、第一层或者new一个新对象
相关推荐
小小小小小星3 小时前
鸿蒙开发之ArkUI框架进阶:从声明式范式到跨端实战
harmonyos·arkui
鸿蒙小灰3 小时前
鸿蒙开发对象字面量类型标注的问题
harmonyos
鸿蒙先行者4 小时前
鸿蒙Next不再兼容安卓APK,开发者该如何应对?
harmonyos
YF云飞6 小时前
.NET 在鸿蒙系统(HarmonyOS Next)上的适配探索与实践
华为·.net·harmonyos
Quarkn10 小时前
鸿蒙原生应用ArkUI之自定义List下拉刷新动效
list·harmonyos·arkts·鸿蒙·arkui
AlbertZein11 小时前
HarmonyOS5 凭什么学鸿蒙 —— Context详解
harmonyos
whysqwhw19 小时前
鸿蒙音频播放方式总结
harmonyos
whysqwhw19 小时前
鸿蒙音频录制方式总结
harmonyos
zhanshuo21 小时前
HarmonyOS 实战:用 @Observed + @ObjectLink 玩转多组件实时数据更新
harmonyos
zhanshuo21 小时前
鸿蒙任务调度机制深度解析:优先级、时间片、多核与分布式的流畅秘密
harmonyos