HarmonyOS ArkUI @State 与 @Prop 区别:一个计数器讲清父子组件单向数据流
【摘要】 用一个父子计数器讲清 ArkUI @State 与 @Prop 的区别:@State 是组件自己的源头状态,@Prop 是父传子的单向数据;子组件改 @Prop 不会回传父组件,下一次父状态变化还会覆盖。
前言
今天在 AI DevSpace 里实测了一个 ArkUI 状态管理问题:@State 和 @Prop 到底有什么区别?把结论整理成这篇笔记,并用一个父子计数器做了验证。
一句话结论
@State 是组件自己的“源头状态”,谁定义谁改;@Prop 是子组件从父组件接收的“单向数据”,父变子跟着变,子改了父不知道。
对照表
| 维度 | @State | @Prop |
|---|---|---|
| 作用域 | 当前组件内部 | 子组件内部,值来自父组件 |
| 数据流 | 单向:状态变化 → UI 刷新 | 单向:父组件 @State 变化 → 子组件 @Prop 自动同步 |
| 可修改 | 当前组件内部可以直接赋值修改 | 子组件内部可以修改,但不会回传给父组件 |
| 触发重渲染 | 修改后,当前组件及依赖该状态的 UI 刷新 | 父组件状态变化时,子组件中 @Prop 相关的 UI 刷新 |
| 类比 | 组件的“私有可变状态” | 函数的“值传递参数”,父传子,子改了不影响父 |
计数器示例
@Entry
@Component
struct ParentCounter {
@State count: number = 0
build() {
Column() {
Text(`父组件 count:${this.count}`)
Button('父组件 +1')
.onClick(() => { this.count++ })
ChildCounter({ childCount: this.count })
}
}
}
@Component
struct ChildCounter {
@Prop childCount: number
build() {
Column() {
Text(`子组件 childCount:${this.childCount}`)
Button('子组件局部 +10')
.onClick(() => { this.childCount += 10 })
}
}
}
运行过程验证
- 初始状态:父组件 count = 0,子组件 childCount 接收到 0,两个组件都显示 0。
- 点“父组件 +1”:count 变为 1,父组件 UI 刷新,子组件的 @Prop 自动同步为 1,子组件 UI 也刷新。
- 点“子组件局部 +10”:子组件显示 11,但父组件的 count 仍然是 1——@Prop 是单向的,不会回传。
- 再点“父组件 +1”:count 变为 2,子组件的 childCount 被覆盖为 2,之前局部加的 10 丢了。这验证了 @Prop 的“值传递”本质:子组件的局部修改是临时的。
什么时候用哪个
- 组件自己管理一个状态,不涉及父组件:用 @State。
- 子组件只需要展示父组件的数据,不需要回传:用 @Prop。
- 子组件需要修改父组件的状态(双向同步):用 @Link。
- 跨多层级共享状态:用 @Provide + @Consume。
一个容易踩的坑
在子组件里改 @Prop,以为能同步回父组件,结果下一次父组件状态变化时就被覆盖。需要回传时,改用 @Link,不要在 @Prop 上“硬改”。
小结
@State + @Prop 是最基础的父子单向数据流。理解了它,再去看 @Link(双向)和 @Provide/@Consume(跨层级)就会很自然。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)