HarmonyOS ArkTS 父子传参神器:@Prop 装饰器 全面解析
在 ArkTS/ArkUI 的组件化开发中,组件之间传递数据是最常见的操作。虽然我们有 @State 管理组件内部状态,但父组件如何把数据传到子组件?这时你需要用到:
@Prop 装饰器(属性装饰器) —— 实现父组件向子组件的单向数据同步。华为开发者官网+1
一、什么是 @Prop
简单来说:
@Prop装饰器用于标记子组件属性,让它从父组件接收数据并与父组件保持“单向同步关系”。华为开发者官网
它和普通成员变量、状态变量的区别在于:
- 它不是组件内部状态(不会主动触发自身重新渲染)
- 它是由父组件初始化并驱动更新的
- 它是只会从父到子的“流动”,不会向父反馈变化(除非用双向绑定机制)华为开发者官网+1
二、核心特性(开发者需要理解的本质)
1)单向同步(父 → 子)
父组件的值变化会自动同步到子组件的 @Prop 变量,但:
子组件对这个值的修改,不会反传给父组件。 这意味着它不是双向绑定。华为开发者官网
这类似于 React 的 props,它是“只读的初始值”,不能协助子组件直接改变父组件的数据。
2)变量是“可变的本地副本”
虽然你在子组件内部读取 @Prop,它会随着父组件变化同步;但如果你在子组件内部修改这个变量:
this.count += 1
这个变化只影响当前子组件实例,不会同步回父组件。c.biancheng.net
3)支持的数据类型较丰富
@Prop 支持常见基础类型:
stringnumberbooleanenum数组- 对象
但要注意: 某些复杂类型(嵌套的对象、Map/Set等)在深层同步时可能表现不如预期,需要格外留意。c.biancheng.net
4)不能在根组件里使用
@Prop 只适用于子组件内部,不能在由 @Entry 标记的根(入口)组件里使用,因为根组件没有父组件可以传参给它。华为开发者官网
三、基本使用方式
实际的父子传参过程一般是这样:
- 父组件用命名参数把数据传递给子组件
- 子组件用
@Prop来接收这个数据 - 父组件数据变更时,框架自动同步更新子组件中的
@Prop
四、实战示例
我们做一个非常直观的计数器例子:
子组件:Child.ets
这是一个接收父组件数据的组件:
@Component
struct ChildComponent {
@Prop count: number // 用 @Prop 接收父组件传来的值
build() {
Column({ space: 12 }) {
Text(`子组件看到 count=${this.count}`)
.fontSize(18)
.fontColor('#333')
Button("子组件尝试减一")
.onClick(() => {
this.count -= 1 // 只会影响当前子组件显示,不会回传给父组件
})
}
.padding(16)
}
}
父组件:Parent.ets
父组件内部有一个状态变量,它通过 props 传给子组件:
@Entry
@Component
struct ParentComponent {
@State count: number = 5
build() {
Column({ space: 12 }) {
Text(`父组件 count=${this.count}`)
.fontSize(20)
.fontColor('#111')
Button("父组件 +1", () => {
this.count += 1 // 父组件状态更新后,子组件也会同步刷新
})
// 把父组件的 count 传给子组件
ChildComponent({ count: this.count })
}
.padding(16)
}
}
运行效果预期
✔ 初始: 父组件 count=5 子组件 count=5
✔ 点击“父组件 +1”: 父组件变成 6 子组件自动同步变成 6
✔ 在子组件里点“子组件尝试减一”: 子组件 count 变为 5,但不会影响父组件的 count 值
✔ 再次点击父组件按钮: 父组件变为 7 然后子组件再次同步变为 7
这就体现了:
父 → 子 单向同步;子组件内部的修改不会同步回父组件。 华为开发者官网+1
五、工作原理解析(像人写的理解)
为什么父组件数据变了子组件能自动刷新?背后的原因其实是:
🔹 框架会把 @Prop 标记的属性和对应的父组件数据建立起依赖关系
🔹 当父组件的状态值发生变化时,ArkTS 会重新计算子组件的 UI
🔹 子组件内部改的 @Prop 值不会触发父组件重新渲染,因为这是“副本值变化”而不是“源状态变化”
这也符合声明式 UI 的核心理念: 视图是数据的直接映射(render = f(data)) ,不需要手动操作 DOM/视图刷新。
六、@Prop 的细节和注意点
1)变量要指定类型
在声明 @Prop 时,一定要明确指定变量的类型(string/number等),否则类型推导可能失败,框架无法正确处理。华为开发者官网
2)不要在子组件里期望“改变父组件值”
因为这是单向的同步机制,改变子组件的 @Prop 不会触发父组件刷新。 如果你希望双向同步,可以参考 @Link 装饰器。CSDN
3)数组/对象等数据赋值建议用新的引用
例如:
// 父组件更新数据
this.items = [...this.items, newItem]
这种写法更容易触发框架的重新渲染机制,避免“引用不变造成 UI 不更新”的问题。
4)尽量避免深层传递链过长
虽然你可以把数据从父传到孙子/重孙组件,但建议层级不超过三层,否则维护成本会高,而且数据来源不清晰。
七、与 @State 和 @Link 的比较
为了更清晰地理解 @Prop,常把它和另外两个常见装饰器比较一下:
| 装饰器 | 是否能写入 | 数据同步方向 | 典型用途 |
|---|---|---|---|
@State | ✔ | 组件内部状态 | 管理组件自己的数据 |
@Prop | ✔(但只反映父组件) | 单向父 → 子 | 父组件向子组件传值 |
@Link | ✔ | 双向(父 ↔ 子) | 父子状态共享/双向绑定 |
八、真实业务场景下的使用建议
我们在业务中常常会遇到下面几种父子数据传递模式:
1)静态展示数据传递
例如用户信息卡片组件:
<UserCard name={this.user.name} age={this.user.age} />
只需在子组件用 @Prop 接收即可。
2)表单输入组件绑定
如果只是读取父级数据并做展示,适合用 @Prop;
如果子组件要修改父组件数据(例如输入框实时更新父组件状态),建议使用 @Link。
3)Icon / 视觉辅助组件
如图标颜色、字体大小等静态参数传递,也用 @Prop 最简洁。
九、结语
@Prop 装饰器是 ArkTS 组件开发里最基础、最核心的数据传递机制之一。理解它的“单向同步”本质,有助于你在大中型项目里:
明确组件的职责边界 让组件更易于组合与复用 避免无效刷新与重复逻辑 保持数据流清晰(父 → 子)