状态管理在鸿蒙中的最佳实践:@State / @Prop / @Link 详解 HarmonyOS 5.0.0
·
在鸿蒙 ArkTS 中,状态就是一切。
组件会自动根据状态变化更新 UI,无需你手动操作 DOM 或调用刷新方法。
但很多开发者初学 ArkTS 时,对状态装饰器 @State、@Prop 和 @Link 的用法常常一头雾水。
今天,我们就来一次彻底的解析和实战演练,帮助你真正掌握 ArkTS 的响应式状态体系。
✅ 三大状态装饰器简介
| 装饰器 | 用途 | 响应式性 | 可写性 | 适用场景 |
|---|---|---|---|---|
@State |
组件内部状态 | ✅ | ✅ | 本组件状态控制 |
@Prop |
接收父组件传入的值 | ✅ | ❌ | 父传子只读值 |
@Link |
绑定状态引用,子组件可读写(双向) | ✅ | ✅ | 父子组件共享状态 |
🎯 示例:构建一个父子共享状态的点赞组件
目标:
- 父组件展示点赞数;
- 子组件点击按钮增加点赞;
- 实现状态的单向传递(@Prop)与双向绑定(@Link)。
📦 Step1:子组件 LikeButton.ets
@Component
export struct LikeButton {
@Link likeCount: number
build() {
Row({ space: 10 }) {
Text(`点赞:${this.likeCount}`)
.fontSize(18)
Button('👍 点赞')
.onClick(() => this.likeCount++)
}
}
}
@Link使得子组件既可以读取,又能修改父组件传入的状态。
📦 Step2:父组件 LikePage.ets
@Entry
@Component
struct LikePage {
@State likeCount: number = 0
build() {
Column({ space: 20 }) {
Text(`总点赞数:${this.likeCount}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
LikeButton({ likeCount: $link(this.likeCount) })
}
.padding(20)
}
}
注意这行代码:
LikeButton({ likeCount: $link(this.likeCount) })
- 通过
$link()把@State状态包装为一个响应式引用,传递给子组件的@Link。
🧪 对比:@Prop 与 @Link 的区别
如果将上面的 @Link 改为 @Prop:
@Prop likeCount: number
即变成只读,子组件就不能修改 likeCount,点击按钮不会生效。这正是 @Prop 的限制。
🔁 @State 的自动响应式
再举一个例子:倒计时计数器。
@Entry
@Component
struct TimerPage {
@State counter: number = 10
aboutToAppear() {
setInterval(() => {
if (this.counter > 0) this.counter--
}, 1000)
}
build() {
Column() {
Text(`倒计时:${this.counter}秒`)
.fontSize(30)
.fontColor(Color.Red)
}
.padding(50)
}
}
只要 this.counter-- 被调用,UI 自动更新,无需额外操作。
📌 状态变更提示技巧
ArkTS 不会提示你 “哪些状态会触发重渲染”,建议:
- 所有需要 UI 更新的值都用
@State管理; - 父子传值需考虑是否需要写入:用
@Link替代@Prop。
🧱 状态封装建议
当组件变复杂,可以将状态和逻辑抽到外部模块:
// state/useCounter.ts
export function useCounter() {
let count: number = 0
function increment() {
count++
}
return {
count,
increment
}
}
再在组件中使用该逻辑,便于复用。
🧩 总结
| 场景 | 推荐使用 |
|---|---|
| 本组件私有状态 | @State |
| 父传子只读参数 | @Prop |
| 父子双向共享(需要子写入) | @Link |
📘 下一篇预告
《ArkTS 网络请求全流程:从 Http 到数据渲染》
你将学会封装 API 模块、处理异步请求、渲染接口数据,并优雅地展示 Loading/异常状态。
更多推荐


所有评论(0)