一、介绍
资料来自官网:文档中心
在声明式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:stringbuild() {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:stringbuild() {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可以通过相同的变量名或者相同的变量别名绑定,变量类型必须相同。