页面级变量的状态管理
@State、@Prop、@Link、@Provide、@Consume、@ObjectLink、@Observed和@Watch用于管理页面级变量的状态。
@State
@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。
@State状态数据具有以下特征:
- 支持多种类型数据:支持class、number、boolean、string强类型数据的值类型和引用类型,以及这些强类型构成的数组,即Array<class>、Array<string>、Array<boolean>、Array<number>。不支持object和any。
- 支持多实例:组件不同实例的内部状态数据独立。
- 内部私有:标记为@State的属性是私有变量,只能在组件内访问。
- 需要本地初始化:必须为所有@State变量分配初始值,变量未初始化可能导致未定义的框架异常行为。
- 创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定@State状态变量的初始值。
示例:
在下面的示例中:
-
用户定义的组件MyComponent定义了@State状态变量count和title。如果count或title的值发生变化,则执行MyComponent的build方法来重新渲染组件;
-
EntryComponent中有多个MyComponent组件实例,第一个MyComponent内部状态的更改不会影响第二个MyComponent;
-
创建MyComponent实例时通过变量名给组件内的变量进行初始化,如:
MyComponent({ title: { value: 'Hello World 2' }, count: 7 })
// xxx.ets
class Model {
value: string
constructor(value: string) {
this.value = value
}
}
@Entry
@Component
struct EntryComponent {
build() {
Column() {
MyComponent({ count: 1, increaseBy: 2 }) // 第1个MyComponent实例
MyComponent({ title: { value: 'Hello World 2' }, count: 7 }) // 第2个MyComponent实例
}
}
}
@Component
struct MyComponent {
@State title: Model = { value: 'Hello World' }
@State count: number = 0
private toggle: string = 'Hello World'
private increaseBy: number = 1
build() {
Column() {
Text(`${this.title.value}`).fontSize(30)
Button('Click to change title')
.margin(20)
.onClick(() => {
// 修改内部状态变量title
this.title.value = (this.toggle == this.title.value) ? 'Hello World' : 'Hello ArkUI'
})
Button(`Click to increase count=${this.count}`)
.margin(20)
.onClick(() => {
// 修改内部状态变量count
this.count += this.increaseBy
})
}
}
@Prop
@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但变量的更改不会通知给父组件,父组件变量的更改会同步到@prop装饰的变量,即@Prop属于单向数据绑定。
@Prop状态数据具有以下特征:
- 支持简单类型:仅支持number、string、boolean等简单数据类型;
- 私有:仅支持组件内访问;
- 支持多个实例:一个组件中可以定义多个标有@Prop的属性;
- 创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有@Prop变量,不支持在组件内部进行初始化。
说明:
@Prop修饰的变量不能在组件内部进行初始化。
示例:
在下面的示例中,当按“+1”或“-1”按钮时,父组件状态发生变化,重新执行build方法,此