鸿蒙学习笔记 11 @State装饰器

状态管理

要说State, 就必须要聊聊状态管理. 状态就是视图上需要更新的一些内容, 在ArkUI中, 只有状态发生变化, 只有经过State修饰过的数据发生变化, 才会执行build函数, 进而更新页面.

而且我们可能会有通过点击, 修改状态的需求, 这就叫做状态管理了. 有很多状态管理的装饰器, 这里先介绍最基本的State装饰器. 有以下注意点:

  • @State标记的变量必须进行初始化, 不能为空
  • @State支持的数据类型有限, 只支持Object, class, string, number, boolean, enum, 以及对于类型的数组. 对于any之类的复杂类型是不允许的.
  • 对于嵌套类型, Object里面嵌套一些其他东西, 这些东西改变了, 无法触发视图更新.

接下来就测试这几个特性.

@State 特性

搭建框架

在页面中间显示一个文本, 点击文本后更改显示的文字:

@Entry
@Component
struct Index {
  @State message: string = "Hello"

  build() {
    Column() {
      Row() {
        Text(this.message)
          .fontSize(40)
          .fontWeight(FontWeight.Bolder)
      }
      .height("100%")
    }
    .width("100%")
  }
}

变量必须初始化

其实只要你把后面的初始化删掉就能看出来了:

在这里插入图片描述

支持数据类型

给一个学生类, 正常定义即可:

class Student {
  name: string
  age: number

  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }
}

尝试使用State修饰一个Student对象, 并且访问它的两个属性:

@Entry
@Component
struct Index {
  @State stu: Student = new Student("Kaede", 18)

  build() {
    Column() {
      Row() {
        Text(`${this.stu.name} : ${this.stu.age}`)
          .fontSize(40)
          .fontWeight(FontWeight.Bolder)
          .onClick(() => {
            this.stu.age++
          })
      }
      .height("100%")
    }
    .width("100%")
  }
}

测试后, 发现普通的对象属性发生变化, 还是可以被检测到的.

在这里插入图片描述

不支持嵌套

比如说给一个Student对象, 里面嵌套一个ID对象, 我如果不修改Student对象的属性, 那么这个ID是不会变化的:

class ID {
  id: number

  constructor(id: number) {
    this.id = id
  }
}

class Student {
  name: string
  age: number
  id: ID

  constructor(name: string, age: number, id: number) {
    this.name = name
    this.age = age
    this.id = new ID(id)
  }
}

@Entry
@Component
struct Index {
  @State stu: Student = new Student("Kaede", 18, 20)

  build() {
    Column() {
      Row() {
        Text(`${this.stu.name} : ${this.stu.age}\nID = ${this.stu.id.id}`)
          .fontSize(40)
          .fontWeight(FontWeight.Bolder)
          .onClick(() => {
            this.stu.id.id--
          })
      }
      .height("100%")
    }
    .width("100%")
  }
}

点击后不会变化
不过呢, 如果你非要显示, 那么你可以触发一下this.stu属性的变化, 也就是触发外层的更改, 这样内层就会一起更改了.

State应用

修饰数组 动态渲染

数组的类型可以直接是对象数组, 比如下面这样子, 创建一个ID列表:

@State ids: ID[] = [
  new ID(1),
  new ID(2),
  new ID(3)
]

随后, 我们使用循环渲染, 将这些ID渲染出来

@Entry
@Component
struct Index {
  @State ids: ID[] = [
    new ID(1),
    new ID(2),
    new ID(3)
  ]

  build() {
    Row() {
      Column() {
        /// 循环渲染
        Text("循环渲染")
          .fontSize(40)
        ForEach(this.ids, (item: ID, index) => {
          Text(`ID = ${item.id}`)
            .fontSize(30)
        })
      }
      .width("100%")
    }
    .height("100%")
  }
}

在这里插入图片描述
首先试试操作数组, 比如添加元素, 是否会触发修改. 下面提供一个按钮来添加元素即可:

// 添加元素
Button("添加一个项目").onClick(() => {
  this.ids.push(new ID(Math.random()))
})

这里使用了一下随机数函数, 也可以定义额外变量来记录当前数据.

点击按钮, 发现成功了, 动态渲染√

在这里插入图片描述
现在想要实现, 点击对应条目就删除, 怎么实现呢? 因为我们刚刚是有index的, 所以可以直接根据index进行删除. 直接添加一个onClick函数方法即可

ForEach(this.ids, (item: ID, index) => {
  Text(`ID = ${item.id}`)
    .fontSize(30)
    .onClick(() => {
      // 这里使用一个方法, 第一个传入下表, 第二个传入删除的个数
      // 自然就是只删除一个内容, 1就好
      this.ids.splice(index, 1)
    })
})

End

感谢阅读, 这就是State装饰器的装饰作用. 还请牢记装饰器的几个重要特点:

  • @State标记的变量必须进行初始化, 不能为空
  • @State支持的数据类型有限, 只支持Object, class, string, number, boolean, enum, 以及对于类型的数组. 对于any之类的复杂类型是不允许的.
  • 对于嵌套类型, Object里面嵌套一些其他东西, 这些东西改变了, 无法触发视图更新.

感谢阅读, 希望有帮到你!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kaede清水枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值