目录
- HarmonyOS Next 状态管理:Local 装饰器实践
- HarmonyOS Next 状态管理:Param 装饰器实践
- HarmonyOS Next 状态管理:Once 装饰器实践
- HarmonyOS Next 状态管理:Event 装饰器实践
- HarmonyOS Next 状态管理:!! 状态装饰器实践
- HarmonyOS Next 状态管理:@ObserverV2和@Trace 装饰器实践
- HarmonyOS Next 状态管理:Provider和Consumer 装饰器实践
一. !! 修饰器概述
!! 是一种语法糖,用于实现父子组件之间的双向数据绑定。它主要用于初始化子组件中的 @Param 和 @Event,其中 @Event 的命名规则为 $ + @Param 属性名。
- 双向绑定:当父子组件中使用
!!语法时,父组件的数据变化会同步到子组件,子组件的数据变化也会同步到父组件。 - 单向绑定:如果父组件未使用
!!语法,则数据流是单向的,父组件的变化不会同步到子组件。
二. !! 场景事件
2.1 简单使用!!实现双向绑定
@Entry
@ComponentV2
struct Index {
@Local name: string = "父组件"
build() {
Column({space: 20}) {
Text(`${this.name}`)
Button('父组件中修改值')
.onClick(() => {
this.name = `父组件中:${Math.round(Math.random() * 100)}`
})
Line().width('100%').height(1).backgroundColor(Color.Gray)
ChildComponent({cName: this.name!!})
}
}
}
@ComponentV2
struct ChildComponent {
@Param cName: string = "子组件"
@Event $cName: (name: string) => void
build() {
Column() {
Text(`${this.cName}`)
Button('子组件中修改值')
.onClick(() => {
this.$cName(`子组件中:${Date().toString()}`)
})
}
}
}
关键点:
- 父组件更新:父组件中状态变量的变化会同步到子组件。
- 子组件更新:子组件中状态变量的变化会同步到父组件。
- 命名规则:
@Event的命名格式为$ + @Param 属性名。 - 语法糖:父组件中传递参数时需在变量后添加
!!。
2.2 !! 的声明与使用差异
@Entry
@ComponentV2
struct Index {
@Local name: string = "父组件"
build() {
Column({space: 20}) {
Text(`${this.name}`)
Button('父组件中修改值')
.onClick(() => {
this.name = `父组件中:${Math.round(Math.random() * 100)}`
})
Line().width('100%').height(1).backgroundColor(Color.Gray)
ChildComponent({cName: this.name!!})
Line().width('100%').height(1).backgroundColor(Color.Gray)
AnotherChildComponent({aName: this.name})
}
}
}
@ComponentV2
struct ChildComponent {
@Param cName: string = "子组件"
@Event $cName: (name: string) => void
build() {
Column() {
Text(`${this.cName}`)
Button('子组件中修改值')
.onClick(() => {
this.$cName(`子组件中:${Date().toString()}`)
})
}
}
}
@ComponentV2
struct AnotherChildComponent {
@Param aName: string = "another子组件"
@Event $aName: (name: string) => void = (name: string) => {}
build() {
Column() {
Text(`another: ${this.aName}`)
Button('another子组件中修改值')
.onClick(() => {
this.$aName(`another中:abc`)
})
}
}
}
关键点:
- 双向绑定:使用
!!语法时,父子组件之间的数据变化是双向的。 - 单向绑定:未使用
!!语法时,数据流是单向的,子组件无法将数据变化同步回父组件。
2.3 多层组件数据更新
在日常开发中,通常会封装或抽象出小型可复用的组件,这涉及到多层级组件之间的数据传递。
2.3.1 数据的层级传递
@Entry
@ComponentV2
struct Index {
@Local name: string = "父组件"
build() {
Column({space: 20}) {
Text(`${this.name}`)
Button('父组件中修改值')
.onClick(() => {
this.name = `父组件中:${Math.round(Math.random() * 100)}`
})
Line().width('100%').height(1).backgroundColor(Color.Gray)
ChildComponent({cName: this.name!!})
}
}
}
@ComponentV2
struct ChildComponent {
@Param cName: string = "子组件"
@Event $cName: (name: string) => void
build() {
Column({space: 20}) {
Text(`${this.cName}`)
Button('子组件中修改值')
.onClick(() => {
this.$cName(`子组件中:${Date().toString()}`)
})
Line().width('100%').height(1).backgroundColor(Color.Gray)
ItemComponent({iName: this.cName!!})
}
}
}
@ComponentV2
struct ItemComponent {
@Param iName: string = "iName"
@Event $iName: (name: string) => void = (name: string) => {}
build() {
Column({space: 20}) {
Text(`item:${this.iName}`)
Button('item更新数据')
.onClick(() => {
this.$iName(`item:${Math.round(Math.random() * 100)`)
})
}
}
}
关键点:
- 数据传递:数据可以从父组件传递到子组件,再到更深层级的组件。
- UI 刷新:只有父组件和直接子组件的数据更新会触发 UI 刷新。
- 局限性:
!!语法糖不支持多层级组件之间的双向数据绑定。
2.3.1 实现数据的多层级传递
@Entry
@ComponentV2
struct Index {
@Local name: string = "父组件"
build() {
Column({space: 20}) {
Text(`${this.name}`)
Button('父组件中修改值')
.onClick(() => {
this.name = `父组件中:${Math.round(Math.random() * 100)}`
})
Line().width('100%').height(1).backgroundColor(Color.Gray)
ChildComponent({cName: this.name!!})
}
}
}
@ComponentV2
struct ChildComponent {
@Param cName: string = "子组件"
@Event $cName: (name: string) => void
build() {
Column({space: 20}) {
Text(`${this.cName}`)
Button('子组件中修改值')
.onClick(() => {
this.$cName(`子组件中:${Date().toString()}`)
})
Line().width('100%').height(1).backgroundColor(Color.Gray)
ItemComponent({iName: this.cName,
$iName: (name: string) => {
this.$cName(name)
}})
}
}
}
@ComponentV2
struct ItemComponent {
@Param iName: string = "iName"
@Event $iName: (name: string) => void = (name: string) => {}
build() {
Column({space: 20}) {
Text(`item:${this.iName}`)
Button('item更新数据')
.onClick(() => {
this.$iName(`item:${Math.round(Math.random() * 100)}`)
})
}
}
}
关键点:
- 回调机制:通过回调函数实现多层级组件之间的数据传递。
- 双向绑定:
!!语法糖仅支持父子组件之间的双向绑定,多层级组件间的数据传递需手动实现。 - 灵活性:通过回调函数,可以实现更复杂的数据流控制。
三、总结
- 双向绑定:
!!语法糖简化了父子组件之间的双向数据绑定,提升了开发效率。 - 单向绑定:未使用
!!时,数据流是单向的,子组件无法将数据变化同步回父组件。 - 多层级数据传递:
!!语法糖不支持多层级组件之间的双向绑定,需通过回调函数手动实现。
通过合理使用 !! 语法糖和回调机制,可以有效管理组件之间的数据流,确保数据的同步更新和 UI 的正确刷新。
1532

被折叠的 条评论
为什么被折叠?



