状态管理
在声明式UI中,是以状态驱动视图更新
状态:指驱动视图更新的数据(被装饰器标记的变量)
- @State
- @Prop 和 @Link
- @Provide和 @Consume
@State
- @State装饰器标记的变量必须初始化,不能为空值
- @State支持Object 、class、string、number、boolean、enum 类型以及这些类型的数组
- 嵌套类型以及数组中的对象属性无法触发视图更新
无法触发视图更新的代码示例如下:
嵌套类型无法刷新视图
// 嵌套类型
class Person{
name:string
age:number
friend:Person
constructor(name:string,age:number,friend?:Person) {
this.name=name
this.age=age
this.friend=friend
}
}
@Entry
@Component
struct Index {
@State xiaoming: Person = new Person('xiaoming',13)
@State xiaohong: Person = new Person('xiaohong',14,new Person("lilei",14))
build() {
Row() {
Column() {
Text(this.xiaoming.name+"的年龄"+this.xiaoming.age)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.onClick(()=>{
// 会刷新ui
this.xiaoming.age++
})
Text(this.xiaohong.name+"的朋友的年龄"+this.xiaohong.friend.age)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.onClick(()=>{
// 嵌套类型,不会刷新ui
this.xiaohong.friend.age++
})
}
.width('100%')
}
.height('100%')
}
}
数组中的对象属性无法触发视图更新
class Person {
name: string
age: number
friend: Person
constructor(name: string, age: number, friend?: Person) {
this.name = name
this.age = age
this.friend = friend
}
}
@Entry
@Component
struct Index {
@State xiaoming: Person = new Person('xiaoming', 13)
@State friendList: Person[] = [
new Person("lilei", 14),
new Person("lilei2", 15)
]
build() {
Row() {
Column() {
Text("朋友列表")
.fontSize(40)
.fontWeight(FontWeight.Bold)
Button("添加朋友")
.onClick(() => {
// 点击会增加
let friendIndex = this.friendList.length
this.friendList.push(new Person("lilei" + friendIndex, 20))
})
ForEach(this.friendList, (item, index) => {
Row({space:10}) {
Text(item.name + "的年龄" + item.age)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.onClick(() => {
// 点击不会发生年龄变更
item.age++
})
Button("删除朋友")
.onClick(() => {
// 点击会删除当前项
this.friendList.splice(index, 1)
})
}.width('100%').justifyContent(FlexAlign.SpaceAround)
.margin({bottom:10,left:10,right:10})
.borderRadius(15)
.padding(10)
.backgroundColor('#cccccc')
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Start)
}
.height('100%')
}
}
应用示例
涉及内容:
基础组件:Progress CheckBox
容器组件:Stack List
class Task {
static id: number = 1
name: string = '任务' + Task.id++
isDone: boolean = false
}
@Extend(Text) function finishedTask() {
.decoration({ type: TextDecorationType.LineThrough })
.fontColor('#B1B2B1')
}
@Entry
@Component
struct TaskPage {
// 总任务数量
@State totalTask: number = 0
@State finishTask: number = 0
@State taskList: Array<Task> = []
build() {
Column() {
// 1.顶部任务统计部分
this.TaskProgressView()
// 2.新增任务
Button("新增任务").onClick(() => {
this.taskList.push(new Task())
this.totalTask = this.taskList.length
}).width("60%")
.margin({ top: 10 })
// 3.任务列表
List() {
ForEach(this.taskList, (item, index) => {
ListItem() {
this.TaskItemView(item)
}.swipeAction({ end: this.getDeleteButton(index) })// 向左滑动,出现删除按钮
})
}.layoutWeight(1) // 高度权重
.width('100%')
.alignListItem(ListItemAlign.Center)
}
.width('100%')
.height('100%')
.backgroundColor('#eeeeee')
.justifyContent(FlexAlign.Start)
}
@Builder TaskProgressView() {
Row() {
Text("任务进度:")
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ right: 40 })
Stack() {
Progress({ value: this.finishTask, type: ProgressType.Ring, total: this.totalTask }).width(120)
Text(this.finishTask + "/" + this.totalTask)
.fontSize(20)
.fontWeight(FontWeight.Bold)
}
}.commonCardStyle()
.height(200)
.padding({ left: 20, right: 20 })
.justifyContent(FlexAlign.Center)
}
@Builder TaskItemView(task: Task) {
Row() {
// 这里不生效,原因:state 数组对象嵌套不刷新视图
if (task.isDone) {
Text(task.name)
.fontSize(15)
.fontWeight(FontWeight.Bold)
.margin({ right: 40 })
.finishedTask()
} else {
Text(task.name)
.fontSize(15)
.fontWeight(FontWeight.Bold)
.margin({ right: 40 })
}
Checkbox()
.select(task.isDone).onChange((isChecked) => {
task.isDone = isChecked
this.finishTask = this.taskList.filter(item => item.isDone).length
})
}.commonCardStyle()
.height(100)
.padding({ left: 20, right: 20 })
.justifyContent(FlexAlign.SpaceBetween)
}
@Builder getDeleteButton(index: number) {
Button({ type: ButtonType.Circle }) {
Image($r('app.media.del'))
}
.onClick(() => {
this.taskList.splice(index, 1)
this.finishTask = this.taskList.filter(item => item.isDone).length
this.totalTask = this.taskList.length
})
.width(50)
.height(50)
.padding(10)
.margin({ right: 5 })
.backgroundColor('#ffffff')
}
@Styles commonCardStyle(){
.width('95%')
.margin({ left: 10, right: 10, top: 10 })
.borderRadius(20)
.backgroundColor('#ffffff')
.shadow({ radius: 6, color: '#1f000000', offsetX: 2, offsetY: 4 })
}
}