管理组件拥有的状态
@State修饰符
- @State 装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的 build() 方法刷新UI。
- 支持多种数据类型:允许 class 、 number 、 boolean 、 string 强类型的按值和按引用类型。允许这些强类型构成的数组,即Array、Array、Array、Array。不允许 object 和 any。
- 内部私有:标记为 @State 的属性是私有变量,只能在组件内访问。
- 需要本地初始化:必须为所有 @State 变量分配初始值,将变量保持未初始化可能导致框架行为未定义,初始值需要是有意义的值,比如设置 class 类型的值为 null 就是无意义的,会导致编译报错。
使用样例:
@Entry
@Component
struct ComponentTest {
@State date: string = "时间:" + new Date().getTime(); // data变化会触发build方法执行
build() {
Column({space: 10}) {
Text(`父组件【${this.date}】`) // 显示时间
.fontSize(20)
.backgroundColor(Color.Pink)
Item() // 子组件
Item() // 子组件
Button('更新时间')
.onClick(() => {
this.date = "时间:" + new Date().getTime(); // 点击按钮,date变化,会触发build方法执行
})
}
.width('100%')
.height('100%')
.padding(10)
}
}
// 自定义子组件
@Component struct Item {
@State time: string = "时间:" + new Date().getTime();
build() {
Text(`子组件【${this.time}】`)
.fontSize(20)
.backgroundColor(Color.Grey)
.onClick(() => {
this.time = "时间:" + new Date().getTime(); // 点击更新时间,执行build方法
})
}
}
@Prop修饰符
- @Prop与@State有相同的语义,但初始化方式不同,@Prop装饰的变量可以和父组件的@State变量建立单向的数据绑定。即@Prop修饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量值但更改不会通知父组件。
- 支持简单数据类型:仅支持 number 、 string 、 boolean 简单类型;
- 内部私有:标记为 @Prop 的属性是私有变量,只能在组件内访问。
- 不支持内部初始化:在创建组件的新实例时,必须将值传递给 @Prop 修饰的变量进行初始化,不支持在组件内部进行初始化。
使用样例:
@Entry
@Component
struct ComponentTest {
@State date: string = "时间:" + new Date().getTime();
build() {
Column({ space: 10 }) {
Text(`父组件【${this.date}】`)
.fontSize(20)
.backgroundColor(Color.Pink)
Item({ time: this.date }) // 必须初始化子组件的time字段
Item({ time: this.date }) // 必须初始化子组件的time字段
Button('更新时间')
.onClick(() => {
this.date = "时间:" + new Date().getTime(); // 父组件的更改影响子组件
})
}
.width('100%')
.height('100%')
.padding(10)
}
}
@Component
struct Item {
@Prop time: string; // 不允许本地初始化
build() {
Text(`子组件【${this.time}】`)
.fontSize(20)
.backgroundColor(Color.Grey)
.onClick(() => {
this.time = "时间:" + new Date().getTime(); // 子组件的更改不影响父组件
})
}
}
@Link修饰符
- @Link装饰的变量可以和父组件建立双向同步关系,子组件中@Link装饰变量的修改会同步给父组件中建立双向数据绑定的数据源,父组件的更新也会同步给@Link装饰的变量。
- 支持多种数据类型: @Link 变量的值与 @State 变量的类型相同,即 class 、 number 、 string 、 boolean 或这些类型的数组。
- 内部私有:标记为 @Link 的属性是私有变量,只能在组件内访问。
- 不支持内部初始化:在创建组件的新实例时,必须将值传递给 @Link 修饰的变量进行初始化,不支持在组件内部进行初始化。初始化使用 $ 符号,例如:$propertiesName。
样例:
@Entry
@Component
struct ComponentTest {
@State date: string = "时间:" + new Date().getTime(); // 定义@State变量
build() {
Column({space: 10}) {
Text(`父组件【${this.date}】`)
.fontSize(20)
.backgroundColor(Color.Pink)
Item({time: $date}) // 初始化子组件time属性使用$符号
Item({time: $date}) // 初始化子组件time属性使用$符号
Button('更新时间')
.onClick(() => {
this.date = "时间:" + new Date().getTime(); // 变更date,子组件的对应属性也变化
})
}
.width('100%')
.height('100%')
.padding(10)
}
}
@Component struct Item {
@Link time: string;
build() {
Text(`子组件【${this.time}】`)
.fontSize(20)
.backgroundColor(Color.Grey)
.onClick(() => {
this.time = "时间:" + new Date().getTime(); // 变更time,父组件的对应属性也变化
})
}
}
@Provide/@Consume装饰器:与后代组件双向同步
- @Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。
- 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。
- @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。
@Watch修饰符 - @Watch 用来监听状态变量的变化,当它修饰的状态变量发生变更时,回调相应的方法。
样例:
@Entry
@Component
struct WatchTest {
@State @Watch("onBasketUpdated") shopBasket: Array<number> = [7, 12, 47, 3];
@State totalPurchase: number = 0;
updateTotal(): number {
let sum = 0;
this.shopBasket.forEach((i) => {
sum += i;
});
// 计算新的购物篮总价值,如果超过100RMB,则适用折扣
this.totalPurchase = (sum < 100) ? sum : 0.9 * sum;
return this.totalPurchase;
}
onBasketUpdated(propName: string): void {
this.updateTotal();
}
build() {
Column({space: 10}) {
Text(`${this.totalPurchase}`)
.fontSize(30)
Button("add to basket")
.onClick(() => {
this.shopBasket.push(Math.round(100 * Math.random()))
})
}
.width("100%")
.height("100%")
.padding(10)
}
}