一、介绍
资料来自官网:文档中心
在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。
- View(UI):UI渲染,指将build方法内的UI描述和@Builder装饰的方法内的UI描述映射到界面。
- State:状态,指驱动UI更新的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。
说明:
@State装饰器标记的变量必须初始化,不能为空值
@State支持Object、class、string、number、boolean、enum类型以及这些类型的数组
嵌套类型以及数组中的对象属性无法触发视图更新
二、父子组件数据同步
2.1、@Prop装饰器:父子单向同步
@Prop装饰的变量可以和父组件建立单向的同步关系。@Prop装饰的变量是可变的,但是变化不会同步回其父组件。
@Entry
@Component
struct StatePage {
@State name: string = '汤姆'
build() {
Row() {
Column({space:8}) {
Text(this.name)
.StatePage_textSty()
// 父组件的数据源的修改会同步给子组件
Button('点我')
.StatePage_btnSty(() => this.name = this.name === '汤姆' ? '杰克' : '汤姆')
Divider()
PropPage({contentProp:this.name})
}
.width('100%')
}
.height('100%')
}
}
//存放一个@Prop装饰的状态数据,方便父子组件数据传递 State ---> Prop
@Component
struct PropPage {
@Prop contentProp:string
build() {
Column({space:8}){
Text('prop--' + this.contentProp)
.StatePage_textSty()
// @Prop装饰的变量不会同步给父组件
Button('修改prop的值')
.StatePage_btnSty(() => this.contentProp = '杰克逊')
}
}
}
//text和button重复的样式进行复用
@Extend(Text) function StatePage_textSty(){
.fontSize(30)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Green)
}
@Extend(Button) function StatePage_btnSty(click:Function){
.fontSize(30)
.onClick(() => click())
}
上面示例中:
父组件StatePage,子组件PropPage
①当点击父组件的按钮时,父组件的name发生变化,子组件的contentProp 也发生了变化
②当点击子组件的按钮时,子组件的contentProp 发生变化,但父组件的name未改变
✍使用@Prop,父子单向同步
2.2、@Link装饰器:父子双向同步
@Link装饰的变量与其父组件中的数据源共享相同的值。
限制条件:@Link装饰器不能在@Entry装饰的自定义组件中使用
上面示例中:
父组件StatePage,子组件LinkPage
①当点击父组件的按钮时,父组件的name发生变化,子组件的contentLink也发生了变化
②当点击子组件的按钮时,子组件的contentLink发生变化,父组件的name也发生了变化
✍使用@Link,父子双向同步
三、后代组件双向同步
3.1、@Provide装饰器和@Consume装饰器:与后代组件双向同步
@Provide和@Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。
下面代码具有相同的变量名,使用@Provide和@Consume实现与后代组件数据同步👇
@Entry
@Component
struct ProvideConsume {
@Provide name: string = '关羽'
build() {
Row() {
Column({space:20}) {
Text(this.name)
.ProvideConsume_textStyle()
.onClick(() => this.name = '张飞')
Divider()
ProvideConsume_son()
}
.width('100%')
}
.height('100%')
}
}
@Component
struct ProvideConsume_son {
build() {
Column({space:20}){
Text('子组件:')
.ProvideConsume_textStyle()
Divider()
ProvideConsume_sun()
}
}
}
@Component
struct ProvideConsume_sun{
@Consume name:string
build() {
Column(){
Text('孙组件:'+ this.name)
.ProvideConsume_textStyle()
.onClick(() => {this.name = '刘备'})
}
}
}
@Extend(Text) function ProvideConsume_textStyle(){
.fontSize(30)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Green)
}
下面代码变量名不一致,但具备相同的别名,使用@Provide和@Consume实现与后代组件数据同步👇
上面示例中:
父组件ProvideConsume,子组件ProvideConsume_son,孙组件ProvideConsume_sun
①点击父组件的按钮,父组件的name发生变化,孙组件的name也发生变化
②点击孙组件的按钮,孙组件与父组件的name同时发生变化
✍父组件使用@Provide将name变量给孙组件,孙组件通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步
✍@Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,变量类型必须相同。