前提
- 需要安装
DevEco Studio
开发工具 - 需要有TS基础
@State装饰器
描述
被状态装饰器装饰的变量,改变会引起UI的渲染更新
例子
@Entry
@Component
struct Index {
@State text: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.text)
.onClick(() => {
this.text = 'Hello ArkTS'
})
}
.width('100%')
}
.height('100%')
}
}
点击后视图中的Hello World
会改变为Hello ArkTS
注意!!!
- 允许装饰的变量类型Object、class、string、number、boolean、enum类型,以及这些类型的数组类型必须被指定
- 不支持any,不支持简单类型和复杂类型的联合类型,不允许使用undefined和null
- 必须本地初始化
- 对象嵌套对象 或者 数组嵌套对象 那么内层对象的值发生改变视图是不会变化的 (后面有解决方案)
@Prop装饰器
描述
装饰的变量和父组件建立单向的同步关系
例子
@Entry
@Component
struct Parent {
@State count: number = 0
build() {
Row() {
Column() {
Son({count: this.count})
}
.width('100%')
}
.height('100%')
}
}
@Component
struct Son {
@Prop count: number
build() {
Column() {
Text(this.count.toString())
}
}
}
子组件Son
通过@Prop
定义属性count
,需要父组件Parent
传递count
属性
注意!!!
- 只能通过修改父组件的值传递到子组件,子组件修改不会同步到父组件
- 传递给@Prop装饰的值不能为undefined或者null
- 禁止子组件本地初始化
@Link装饰器
描述
装饰的变量和父组件建立双向的同步关系
例子
@Entry
@Component
struct Parent {
@State count: number = 0
build() {
Row() {
Column() {
Son({count: $count})
}
.width('100%')
}
.height('100%')
}
}
@Component
struct Son {
@Link count: number
build() {
Column() {
Text(this.count.toString())
.onClick(e => {
this.count++
})
}
}
}
子组件Son
通过@Link
定义count
属性,父组件Parent
传递count
给子组件,子组件点击修改父组件传递过来的count
属性是可以触发视图更新的,因为子组件修改值也同步到了父组件
注意!!!
- 父组件传值的方式为 $ + 属性名来表示
- 不允许使用undefined和null
- 禁止子组件本地初始化
@Prop和@Link装饰器的区别
- @Prop 是单向同步的
- @Link 是双向同步的
原因
@Prop
定义的属性是父组件传值时直接覆盖,所以@Prop是值的拷贝
@Link
定义的属性是对值的引用,所以可以实现父子组件双向同步
@Provide装饰器和@Consume装饰器
描述
应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景
例子
// 爷级组件
@Entry
@Component
struct GrandFather {
@Provide name: string = 'zs'
build() {
Row() {
Column() {
Father()
}
.width('100%')
}
.height('100%')
}
}
// 父级组件
@Component
struct Father {
build() {
Column() {
Son()
}
}
}
// 孙级组件
@Component
struct Son {
@Consume name: string
build() {
Column() {
Text(this.name)
.onClick(e => {
this.name = 'ls'
})
}
}
}
GrandFather
组件通过@Provide
定义了name
,Son
组件通过@Consume
定义了name
,内部就会帮我们把这两个值绑定上,孙级组件可以在页面上渲染也可以修改值,也是可以同步到爷级组件的
注意!!!
- 不需要在调用时传值,只需要使用
@Provide
和Consume
定义相同属性名即可传递值 - 不允许使用undefined和null
@Provide
变量的@Consume
变量的类型必须相同
@Observed装饰器和@ObjectLink装饰器
描述
装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步, 解决@State
无法监听对象嵌套问题
例子
@Entry
@Component
struct Index {
@State list: Message[] = []
build() {
Row() {
ForEach(this.list, (msg: Message) => {
MsgItem({ msg: msg })
})
}
}
}
@Observed
class Message{
text: string = '张三'
changeText() {
this.text = '李四'
}
}
@Component
struct MsgItem{
@ObjectLink msg: Message
build() {
Text(this.msg.text)
.padding('5vp')
.backgroundColor(Color.Pink)
.fontColor('#fff')
.onClick(() => {
this.msg.changeText() // 修改文字
})
}
}
数据嵌套对象的情况,看当前例子,我们给每一个单独的
message
创建一个公共的组件,组件接受一个参数msg
使用@ObjectLink
修饰,那么每当message
当中的text
发生改变就会触发视图的更新。这里要注意噢!!!使用@ObjectLink
修饰的属性,他的类必须使用@Observed
修饰,否则会报错
注意!!!
- @Observed类装饰器需要放在class的定义前,使用new创建类对象
- @ObjectLink变量装饰器必须为被@Observed装饰的class实例,必须指定类型