状态管理
要说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里面嵌套一些其他东西, 这些东西改变了, 无法触发视图更新.
感谢阅读, 希望有帮到你!