状态管理
在声明式UI中,是以状态驱动视图更新
状态:指驱动视图更新的数据(被装饰器标记的变量)
- @State
- @Prop 和 @Link
- @Provide和 @Consume
@State
- @State装饰器标记的变量必须初始化,不能为空值
- @State支持Object 、class、string、number、boolean、enum 类型以及这些类型的数组
- 嵌套类型以及数组中的对象属性无法触发视图更新
无法触发视图更新的代码示例如下:
嵌套类型无法刷新视图
// 嵌套类型
class Person{name:stringage:numberfriend:Personconstructor(name:string,age:number,friend?:Person) {this.name=namethis.age=agethis.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(()=>{// 会刷新uithis.xiaoming.age++})Text(this.xiaohong.name+"的朋友的年龄"+this.xiaohong.friend.age).fontSize(20).fontWeight(FontWeight.Bold).onClick(()=>{// 嵌套类型,不会刷新uithis.xiaohong.friend.age++})}.width('100%')}.height('100%')}
}
数组中的对象属性无法触发视图更新
class Person {name: stringage: numberfriend: Personconstructor(name: string, age: number, friend?: Person) {this.name = namethis.age = agethis.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.lengththis.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 = 1name: 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 = isCheckedthis.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).lengththis.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 })}
}