回复
ETS装饰器学习之State、Prop、Link 原创
droidzxy
发布于 2022-11-7 12:20
浏览
0收藏
在学习声明式UI框架ArkUI的过程中,会遇到装饰器的概念,不管是简单的示例页面还是复杂的大程序,都离不开装饰器的使用,为了帮助自己对装饰器有一个基本的了解,并能够熟练的使用,所以专门针对ets装饰器系统的学习了一下,并整理成简单的笔记,以便健忘的我随时回来复习一下。
本文主要介绍@State、@Prop和@Link,@State表示组件内部状态数据,@Prop装饰的变量必须是定义在子组件中,并且在父组件调用的时候进行参数赋值,@Link装饰的变量可以和父组件的@State变量建立双向数据绑定。
@State
@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。
@State状态数据具有以下特征:
- 支持多种类型数据:支持class、number、boolean、string强类型数据的值类型和引用类型,以及这些强类型构成的数组,即Array<class>、Array<string>、Array<boolean>、Array<number>。不支持object和any。
- 支持多实例:组件不同实例的内部状态数据独立。
- 内部私有:标记为@State的属性是私有变量,只能在组件内访问。
- 需要本地初始化:必须为所有@State变量分配初始值,变量未初始化可能导致未定义的框架异常行为。
- 创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定@State状态变量的初始值。
示例代码:
class Model {
value: string
constructor(value: string) {
this.value = value
}
}
@Entry
@Component
struct Index {
@State title: Model = { value: 'Introduction' }
@State index: number = 2
@State message: string = 'This is an example for State'
@State items : Array<string> = ['First item','Second item','Third item']
build() {
Row() {
Column() {
Text(this.index.toString())
.fontSize(50)
.width('100%')
Text(this.title.value)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Start)
Text(this.message)
.fontSize(25)
.width('100%')
ForEach(this.items, item => {
Text(item.toString()).fontSize(18).padding(10)
.width('100%')
.textAlign(TextAlign.Start)
}, item => item.toString())
SubComponent({num: 20})
}
.width('100%')
}
.height('100%')
}
}
@Component
struct SubComponent {
@Prop num: number
build() {
Column() {
Text(`SubComponent num ${this.num} `).fontSize(28)
.fontColor(Color.White)
}
.width('100%')
.backgroundColor(Color.Gray)
}
}
效果预览:
上面示例,分别针对state修饰的变量按照class、number、string、Array<string>
类型进行了实践,需要注意的是必须本地初始化。
@Prop
@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但更改不会通知给父组件,即@Prop属于单向数据绑定。
@Prop状态数据具有以下特征:
- 支持简单类型:仅支持number、string、boolean简单类型;
- 私有:仅在组件内访问;
- 支持多个实例:一个组件中可以定义多个标有@Prop的属性;
- 创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有@Prop变量,不支持在组件内部进行初始化。
示例代码:
@Entry
@Component
struct Index {
@State message: string = 'Prop'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
SubComponent({count : 20})
}
.width('100%')
}
.height('100%')
}
}
@Component
struct SubComponent {
@Prop count: number
build(){
Text("subcomponent member:" + this.count)
.fontSize(25)
}
}
效果预览:
需要注意的是,在子组件中prop变量不能初始化,在父组件调用时,必须给变量赋值。
@Link
@Link装饰的变量可以和父组件的@State变量建立双向数据绑定:
- 支持多种类型:@Link变量的值与@State变量的类型相同,即class、number、string、boolean或这些类型的数组;
- 私有:仅在组件内访问;
- 单个数据源:初始化@Link变量的父组件的变量必须是@State变量;
- 双向通信:子组件对@Link变量的更改将同步修改父组件的@State变量;
- 创建自定义组件时需要将变量的引用传递给@Link变量:在创建组件的新实例时,必须使用命名参数初始化所有@Link变量。@Link变量可以使用@State变量或@Link变量的引用进行初始化,@State变量可以通过’$'操作符创建引用。
示例代码:
@Entry
@Component
struct Index {
@State count: number = 0
build() {
Row() {
Column() {
Text('count=' + this.count)
.fontSize(50)
.fontWeight(FontWeight.Bold)
SubComponent({ subCount: $count })
}
.width('100%')
}
.height('100%')
}
}
@Component
struct SubComponent {
@Link subCount: number
build() {
Button('subCount=' + this.subCount)
.margin(15)
.onClick(() => {
this.subCount += 1
})
}
}
效果预览:
需要注意的是,@Link变量不能在组件内部进行初始化,@State变量要通过’$'操作符创建引用。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
赞
3
收藏
回复
相关推荐