一.状态管理:
ArkUI作为一种声明式UI,具有状态驱动UI更新的特点。当用户进行界面交互或有外部事件引起状态改变时,状态的变化会触发组件自动更新。所以在ArkUI中,我们只需要通过一个变量来记录状态。当改变状态的时候,ArkUI就会自动更新界面中受影响的部分。
ArkUI框架提供了多种管理状态的装饰器来修饰变量,使用这些装饰器修饰的变量即称为状态变量。
二.装饰器:
1.@State装饰器
组件中,由@State装饰的变量是组件内部状态数据,当内部状态数据变化时,会调用所在组件的生成器方法进行界面刷新,因此组件会随着内部状态数据的变化而实时更新。关于@State装饰器需要注意以下几点:
- 组件只能监听到第1层状态数据的改变,内层数据的改变无法触发build生命周期。
- @State 可以装饰 class,number、 boolean、string类型成员,也可以装饰它们构成的数组,如 Array<class>、Array<string>、Array < boolean>、Array<number>,但是,不允许装饰 object 和 any 类型成员。
- 在组件具有多个实例的情况下,各个实例的内部状态数据是独立的。
- 使用@State装饰的变量必须进行本地初始化,否则可能导致框架行为未定义。
- 对于自定义组件,内部状态变量名可以通过构造参数进行初始化。
示例代码:
@Entry
@Component
struct StateExample01 {
@State message:string = "Hello World"
build() {
Column(){
Text(this.message)
.fontSize(50)
.onClick(()=>{
//变量通过@State修饰,点击修改私有变量,然后会自动修改刷新UI
this.message = "Hi Augus"
})
}
.width("100%").height("100%")
.justifyContent(FlexAlign.Center)//主轴方向对齐
}
}
2.@Prop和@Link装饰器
当父子组件之间需要数据同步时,可以使用@Prop和@Link装饰器。
@Prop | @Link | |
同步类型 | 单向同步 | 双向同步 |
允许装饰的变量类型 | @Prop只支持string、number、boolean、enum类型 ,父组件对象类型,自组件对象属性不可以是数组、any | 父子类型一致:string、number、boolean,enum,object,class以及他们的数组。数组中元素增、删、替换会引起刷新。嵌套类型以及数组中的对象属性无法触发页面更新 |
初始化方式 | 不允许子组件初始化 | 父组件传递,禁止子组件初始化 |
示例代码:
@Component
struct MyChild{
@Prop
age:number
private increase:number=1
build(){
Column(){
if(this.age>=18){
Text(`子组件中的age已经成年:${this.age}`)
.height(80)
}
else{
Text(`子组件中的age未成年:${this.age}`)
.height(80)
}
Button('修改子组件年龄')
.onClick(()=>{
this.age-=this.increase
})
.height(80)
.width(250)
.margin(5)
}
}
}
@Entry
@Component
struct MyParent{
@State
init_age:number=16
build(){
Column(){
Text(`父组件中的初始化年龄:${this.init_age}`)
.height(80)
Button('修改父组件年龄')
.onClick(()=>{
this.init_age+=1
})
.height(80)
.width(250)
.margin(5)
Divider()
MyChild({age:this.init_age,increase:2})
}
}
}
class ButtonState{
value:string
width:number=0
constructor(value:string,width:number) {
this.value=value
this.width=width
}
}
@Component
struct myGreenButton{
@Link
buttonState:ButtonState
build(){
Button(`${this.buttonState.value}`)
.width(this.buttonState.width)
.height(150)
.backgroundColor(Color.Green)
.onClick(()=>{
if(this.buttonState.width<700){
this.buttonState.width+=100
}
else{
this.buttonState=new ButtonState('绿色按钮',100)
}
})
}
}
@Component
struct myBlueButton{
@Link
value:string
@Link
buttonWidth:number
build(){
Button(`${this.value}`)
.width(this.buttonWidth)
.height(150)
.backgroundColor(Color.Blue)
.onClick(()=>{
this.buttonWidth+=50
})
}
}
@Entry
@Component
struct MyParent {
@State parentGreenButton:ButtonState=new ButtonState('壹号子组件',300)
@State parentValue:string='二号子组件'
@State parentBlueWidth:number=200
build() {
Column() {
Button(`父组件中修改蓝色按钮的宽度:${this.parentBlueWidth}`)
.onClick(()=>{
this.parentBlueWidth=this.parentBlueWidth<700?this.parentBlueWidth+100:100
})
Button(`父组件中修改绿色按钮的宽度:${this.parentGreenButton.width}`)
.onClick(()=>{
this.parentGreenButton.width=this.parentGreenButton.width<700?this.parentGreenButton.width+100:100
})
Divider()
myGreenButton({buttonState:$parentGreenButton})
myBlueButton({value:$parentValue,buttonWidth:$parentBlueWidth})
}
}
}
3.@Provide和@Consume装饰器
@Provide和Consume可以跨组件提供类似@State和@Link的双向同步
4.@ObjectLink 和@Observed
@ObjectLink 和@Observed 装饰器用于在涉及嵌套对象和数组元素为对象时的场景中进行双向数据同步。
示例代码:
1.嵌套对象使用@Observed 修饰:
@Observed
class Task {
static id: number = 1
name: string = '任务' + Task.id++
isDone: boolean = false
}
2.需要根据嵌套对象属性的变更而刷新视图的组件,通过传入参数且该参数需要被@ObjectLink装饰:
@Component
struct TaskItemView {
@ObjectLink task: Task
onTaskChange: () => void
build() {}
}