useState 换个名字叫 @State,仅此而已 —— React 开发者的鸿蒙入门指南(第 3 期)
🔄 写在前面
上一期我们成功跑通了第一个 HarmonyOS 页面,很多 React 开发者留言问:
“那状态怎么管理?有 useState 吗?”
答案是:有,而且更简单——它叫 @State。
本期我们将深入 HarmonyOS 的状态系统,用你最熟悉的 React 思维,掌握 @State、@Prop、@Link 三大装饰器,并实现一个可交互的“消息编辑器”。
你会发现:鸿蒙的状态管理,不过是 React props 和 state 的另一种表达。
🔁 1. 组件内状态:@State = useState
React 写法
const Counter = () => {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
};
ArkTS 写法
@Component
struct Counter {
@State count: number = 0; // ← 响应式状态声明
build() {
Button(`Count: ${this.count}`)
.onClick(() => {
this.count += 1; // ← 直接赋值,自动触发 UI 更新
})
}
}
✅ 核心机制对比
| 特性 | React | ArkTS |
|---|---|---|
| 状态声明 | const [val, setVal] = useState() |
@State val: Type = init |
| 状态更新 | 调用 setVal(newValue) |
直接赋值 this.val = newValue |
| 更新触发 | 虚拟 DOM diff | 声明式 UI 引擎自动重绘 |
| 是否需记忆化 | 有时需要 useCallback |
不需要 |
💡 关键理解:在 ArkTS 中,状态即 UI 的源头。只要
@State变量变化,依赖它的 UI 自动刷新——无需手动调用更新函数。
📦 2. 父子通信:@Prop 与 @Link(props 的两种形态)
React 中,props 是只读的。但在鸿蒙中,根据是否需要双向同步,分为两类:
▶ 场景一:父 → 子(只读)→ @Prop
// 父组件
@Entry
@Component
struct Parent {
@State message: string = 'Hello from Parent';
build() {
Child({ msg: this.message }) // 传递值副本
}
}
// 子组件
@Component
struct Child {
@Prop msg: string; // ← 只读,不能修改
build() {
Text(this.msg)
}
}
⚠️ 若在子组件中写
this.msg = 'new',编译时报错:@Prop is readonly.
▶ 场景二:父 ↔ 子(双向)→ @Link
// 父组件:注意 $ 符号!
build() {
Child({ msg: $message }) // ← $ 表示“传递引用”
}
// 子组件
@Component
struct Child {
@Link msg: string; // ← 双向绑定
build() {
TextInput({ text: this.msg })
.onChange((value) => {
this.msg = value; // ← 修改会同步回父组件!
})
}
}
🔑
$message是 ArkTS 特有语法,表示“创建对message的引用”,类似 Vue 的.sync或 SolidJS 的响应式信号。
⚠️ 3. 新手常见错误(避坑指南)
❌ 错误 1:用普通变量代替响应式状态
build() {
let temp = 'hello'; // ❌ 非响应式,UI 不会更新
}
✅ 正确:所有驱动 UI 的数据必须用 @State / @Prop / @Link 声明。
❌ 错误 2:未初始化 @State
@State count: number; // ❌ 编译错误:必须初始化!
✅ 正确:
@State count: number = 0;
// 或
@State count?: number; // 可选类型,但使用时需判空
❌ 错误 3:在 @Prop 上赋值
@Prop title: string;
// ...
this.title = 'updated'; // ❌ 运行时错误或编译失败
✅ 正确:只读属性不要修改;如需双向,请改用 @Link。
🛠️ 4. 实战:实现一个“消息编辑器”
结合所学,构建一个父子组件联动的编辑器:
// 主页面
@Entry
@Component
struct MessageEditor {
@State message: string = 'Hello, HarmonyOS!';
build() {
Column() {
// 显示区域(只读)
Text(this.message)
.fontSize(20)
.padding(10)
.backgroundColor($r('sys.color.glass_material_outline_secondary'))
// 编辑区域(双向绑定)
MessageInput({ msg: $message })
}
.width('100%')
.padding(20)
}
}
// 输入组件
@Component
struct MessageInput {
@Link msg: string;
build() {
TextInput({
text: this.msg,
placeholder: 'Edit message...'
})
.onChange((value) => {
this.msg = value;
})
}
}
效果:
- 在输入框中打字 → 上方文本实时同步
- 完美实现父子状态联动!

✅ 小结
- ✅
@State= 组件内状态(≈useState) - ✅
@Prop= 只读 props(≈ React props) - ✅
@Link= 双向绑定 props(通过$传递引用) - ✅ 直接赋值即可触发 UI 更新,无需 setter 函数
你不是在学习新范式,而是在用新语法表达已有的 React 思维。
📚 参考资料
系列名称:《React 开发者的鸿蒙入门指南》
🔜 下期预告
《列表渲染不用 map,用 ForEach!》
我们将深入:
- 如何高效渲染长列表?
ForEach的 key 函数怎么写?- 为什么鸿蒙的
List比react-window更省性能?
关注我,持续解锁 React → 鸿蒙实战技能!
✅ 欢迎点赞、收藏、评论交流!你的支持是我持续输出的动力!
✅ 点击主页关注,获取更多前端 × 鸿蒙实战内容!
💬 互动提问:你在使用
@State时遇到过哪些奇怪问题?留言告诉我,点赞最高的问题,下期优先解答!
更多推荐



所有评论(0)