鸿蒙ArkUI状态管理全攻略
自己用→ @State(会刷新) / @Local(不刷新)父传子→ @Prop父子双向→ @Link跨多层全局共享本地持久化监听变化→ @Watch复用 UI→ @Builder。
一、组件内状态(自己用)
1. @State
- 响应式变量,改了自动刷新 UI
- 用于:页面显示、开关、计数、列表
2. @Local
- 非响应式,改了不刷新 UI
- 用于:临时数据、缓存、中间计算
二、父子组件通信(最常用!高频!)
3. @Prop
父 → 子 单向传递,子不能改
@Prop name: string;
- 父传子,只读
- 场景:标题、配置、静态数据
-
在鸿蒙 ArkUI 中,
@Prop装饰器用于建立单向数据同步:父组件将数据传递给子组件,子组件可以修改自己的@Prop副本,但不会自动同步回父组件。如果子组件需要修改父组件的数据,通常有两种方式: -
使用
@Link装饰器(双向同步) -
使用回调函数(通过
@Prop接收值,再通过事件将修改意图通知父组件)
案例:计数器组件
场景:父组件维护一个 count 状态,子组件展示该值并提供“增加”按钮,点击后父组件的 count 增加。
1. 子组件(CounterChild.ets)
@Component
export struct CounterChild {
// 接收父组件传入的值(只读)
@Prop count: number;
// 定义回调,用于通知父组件增加计数的意图
onIncrease?: () => void;
build() {
Column() {
Text(`子组件显示计数:${this.count}`)
.fontSize(20)
.margin(10)
Button('增加')
.onClick(() => {
// 通过回调通知父组件执行增加操作
if (this.onIncrease) {
this.onIncrease();
}
})
.margin(10)
}
.width('100%')
.height(150)
.backgroundColor('#f0f0f0')
.borderRadius(8)
}
}
2. 父组件(ParentPage.ets)
typescript
import { CounterChild } from './CounterChild';
@Entry
@Component
struct ParentPage {
@State parentCount: number = 0;
// 子组件触发的回调:修改父组件状态
private handleIncrease() {
this.parentCount++;
}
build() {
Column() {
Text(`父组件计数:${this.parentCount}`)
.fontSize(24)
.margin(20)
// 使用子组件,传递 prop 和回调
CounterChild({
count: this.parentCount,
onIncrease: this.handleIncrease.bind(this)
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
2. 父组件(ParentPage.ets)
import { CounterChild } from './CounterChild';
@Entry
@Component
struct ParentPage {
@State parentCount: number = 0;
// 子组件触发的回调:修改父组件状态
private handleIncrease() {
this.parentCount++;
}
build() {
Column() {
Text(`父组件计数:${this.parentCount}`)
.fontSize(24)
.margin(20)
// 使用子组件,传递 prop 和回调
CounterChild({
count: this.parentCount,
onIncrease: this.handleIncrease.bind(this) //方法一
onIncrease: (()=>{ //方法二
this.handleIncrease()
})
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
关键点说明
这种方式遵循了单向数据流原则,使数据变化来源清晰,便于维护。
- 父传子,只读
- 场景:标题、配置、静态数据
-
在鸿蒙 ArkUI 中,
@Prop装饰器用于建立单向数据同步:父组件将数据传递给子组件,子组件可以修改自己的@Prop副本,但不会自动同步回父组件。如果子组件需要修改父组件的数据,通常有两种方式: -
使用回调函数(通过
@Prop接收值,再通过事件将修改意图通知父组件) -
@Prop count让子组件能显示父组件的值,且子组件内部可以修改该副本(但不会影响父组件)。 -
子组件通过自定义回调
onIncrease将修改意图传递给父组件。 -
父组件在回调中更新
@State parentCount,触发 UI 重新渲染,子组件因@Prop接收到新值而同步显示。
4. @Link
父 ↔ 子 双向同步
@Link count: number;
- 子改 = 父也改
- 场景:开关、表单、弹窗控制
5. @Provide + @Consume
跨多层组件传递(爷 → 孙)
// 父/祖先
@Provide("user") user = { name: "张三" }
// 子孙任意层
@Consume("user") user;
- 不用一层层传
- 场景:用户信息、主题、全局配置
三、全局应用状态(整个 APP 共享)
6. @AppStorage
全局持久化状态(内存)
@AppStorage("token") token: string = "";
- 所有页面共享
- 改了所有页面同步刷新
7. @StorageLink
持久化到本地(关机还在)
@StorageLink("userId") userId: string = "";
- 保存在手机本地存储
- 场景:用户 ID、登录状态、设置
四、UI 渲染 / 性能优化装饰器
8. @Watch
监听状态变化,自动执行函数
@Watch("onCountChange")
@State count: number = 0;
onCountChange() {
console.log("count变了")
}
- 监听变量,一变就做事
- 场景:搜索防抖、数据联动
9. @Builder
自定义 UI 块(复用 UI 片段)
@Builder
itemTitle(title: string) {
Text(title).fontSize(20)
}
- 复用 UI,不用写重复代码
10. @Styles / @Extend
样式复用
@Styles
btnStyle() {
.width(200).height(40)
}
五、生命周期装饰器(构建 / 卸载)
11. @Entry
标记页面入口(只能一个)
12. @Component
标记自定义组件
13. @BuilderParam
组件内传递构建函数
六、最实用总结(背会就能写鸿蒙项目)
数据流动一句话记住:
- 自己用 → @State(会刷新) / @Local(不刷新)
- 父传子 → @Prop
- 父子双向 → @Link
- 跨多层 → @Provide + @Consume
- 全局共享 → @AppStorage
- 本地持久化 → @StorageLink
- 监听变化 → @Watch
- 复用 UI → @Builder
七、我给你一个万能速记表(面试直接背)
表格
| 装饰器 | 作用 | 场景 |
|---|---|---|
| @State | 组件内响应式 | 页面显示数据 |
| @Local | 组件内临时变量 | 缓存 / 计算 |
| @Prop | 父→子单向 | 标题、配置 |
| @Link | 父子双向同步 | 开关、表单 |
| @Provide | 祖先跨层传递 | 用户信息 |
| @Consume | 后代跨层接收 | 页面取值 |
| @AppStorage | 全局状态 | 主题、登录 |
| @StorageLink | 本地持久化 | 用户 ID |
| @Watch | 监听变量变化 | 搜索、联动 |
| @Builder | UI 复用 | 列表项、按钮 |
更多推荐



所有评论(0)