HarmonyOS-Next-状态管理-状态修饰器实践
HarmonyOS Next 状态管理:!! 状态修饰器实践
目录
一. !! 修饰器概述
!!
是一种语法糖,用于实现父子组件之间的双向数据绑定。它主要用于初始化子组件中的
@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.
c N a m e ( ‘ 子组件中: cName(`子组件中:
c
N
am
e
(
‘
子组件中: {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.
c N a m e ( ‘ 子组件中: cName(`子组件中:
c
N
am
e
(
‘
子组件中: {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.
c N a m e ( ‘ 子组件中: cName(`子组件中:
c
N
am
e
(
‘
子组件中: {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.
i N a m e ( ‘ i t e m : iName(`item:
i
N
am
e
(
‘
i
t
e
m
: {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.
c N a m e ( ‘ 子组件中: cName(`子组件中:
c
N
am
e
(
‘
子组件中: {Date().toString()}`)
})
Line().width(‘100%’).height(1).backgroundColor(Color.Gray)
ItemComponent({iName: this.cName,
KaTeX parse error: Expected ‘}’, got ‘EOF’ at end of input: … 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.
i N a m e ( ‘ i t e m : iName(`item:
i
N
am
e
(
‘
i
t
e
m
: {Math.round(Math.random() * 100)}`)
})
}
}
}
关键点 :
- 回调机制 :通过回调函数实现多层级组件之间的数据传递。
- 双向绑定
:
!!
语法糖仅支持父子组件之间的双向绑定,多层级组件间的数据传递需手动实现。 - 灵活性 :通过回调函数,可以实现更复杂的数据流控制。
三、总结
- 双向绑定
:
!!
语法糖简化了父子组件之间的双向数据绑定,提升了开发效率。 - 单向绑定
:未使用
!!
时,数据流是单向的,子组件无法将数据变化同步回父组件。 - 多层级数据传递
:
!!
语法糖不支持多层级组件之间的双向绑定,需通过回调函数手动实现。
通过合理使用
!!
语法糖和回调机制,可以有效管理组件之间的数据流,确保数据的同步更新和 UI 的正确刷新。