鸿蒙开发ArkUI 框架所有装饰器汇总详细解答--通俗易懂
·
「专业+通俗」双拼版讲解,既保证技术准确性,又用生活化比喻让你秒懂鸿蒙装饰器:
🌟 核心装饰器详解(双视角版)
1. @State 组件私有状态
-
专业视角
@State装饰的变量是响应式状态,当值变化时触发当前组件重新渲染。具有组件级作用域,必须初始化默认值。 -
通俗比喻
相当于你自己的「私人钱包」
- 只有你能直接修改里面的钱(组件内修改状态)
- 每次花钱/存钱都会记账(自动更新UI)
- 别人不能动你的钱包(外部不可访问)
- 代码示例:
@Component
struct Counter {
@State count: number = 0 // 你的私房钱
build() {
Button(`点了 ${this.count} 次`)
.onClick(() => this.count++) // 你亲自花钱
}
}
2. @Prop 父子单向传值
-
专业视角
实现父组件到子组件的单向数据流。父组件更新会同步到子组件,但子组件不能直接修改值,需通过事件通知父组件。 -
通俗比喻
相当于「老爸给的零花钱」
- 老爸决定给多少(父组件控制值)
- 你能看到金额但不能改(子组件只读)
- 想加钱得找老爸申请(事件回调)
- 代码示例:
// 父组件(老爸)
Parent() {
@State money: number = 100
Child({ allowance: this.money }) // 给零花钱
}
// 子组件(孩子)
@Component
struct Child {
@Prop allowance: number // 只能看的零花钱
build() {
Text(`零花钱: ${this.allowance}元`)
Button("我要加钱")
.onClick(() => {/* 通知老爸 */}) //❌不能直接 allowance++
}
}
//完整案例
// ======== 父组件 ========
@Entry
@Component
struct Parent {
@State totalMoney: number = 1000; // 老爸的总资金
// 1. 定义更新状态的方法
handleChildRequest(amount: number) {
if (this.totalMoney >= amount) {
this.totalMoney -= amount;
console.log(`老爸转账${amount}元成功,剩余资金: ${this.totalMoney}元`);
} else {
console.log("老爸拒绝:钱不够了!");
}
}
build() {
Column() {
// 显示老爸的资金状态
Text(`老爸总资金: ${this.totalMoney}元`)
.fontSize(20)
.fontColor(Color.Blue)
.margin({ bottom: 20 });
Progress({
value: this.totalMoney,
total: 1000,
type: ProgressType.Ring
})
.width(100)
.height(100)
// 2. 传递状态和回调函数给子组件
Child({
allowance: this.totalMoney * 0.1, // 零花钱 = 总资金的10%
onRequestMoney: (amount: number) => this.handleChildRequest(amount) // 传递回调函数
})
.margin({ top: 30 })
}
.padding(20)
.width('100%')
.height('100%')
.backgroundColor('#f0f0f0')
}
}
// ======== 子组件 ========
@Component
struct Child {
@Prop allowance: number; // 只读零花钱
private onRequestMoney?: (amount: number) => void; // 接收的回调函数
build() {
Column() {
Text(`本月零花钱: ${this.allowance.toFixed(2)}元`)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(this.allowance > 0 ? Color.Green : Color.Red)
Divider().margin(10)
// 3. 子组件触发事件
Button("要50元买书")
.backgroundColor(Color.Blue)
.margin(10)
.onClick(() => {
if (this.onRequestMoney) {
this.onRequestMoney(50); // 调用父组件传递的方法
}
})
Button("要100元买玩具")
.backgroundColor(Color.Orange)
.margin(10)
.onClick(() => {
if (this.onRequestMoney) {
this.onRequestMoney(100);
}
})
Button("要200元买衣服")
.backgroundColor(Color.Purple)
.margin(10)
.onClick(() => {
if (this.onRequestMoney) {
this.onRequestMoney(200);
}
})
}
.padding(20)
.borderRadius(16)
.backgroundColor(Color.White)
.shadow({ radius: 8, color: Color.Grey, offsetX: 2, offsetY: 2 })
}
}
3. @Link 父子双向绑定
-
专业视角
实现父子组件的双向数据同步。需要使用$操作符传递引用,父子任意一方修改都会实时同步。 -
通俗比喻
相当于「家庭联名账户」
- 你和老爸共用一张卡(共享状态)
- 谁花钱/存钱对方立刻知道(双向同步)
- 开账户需要双方同意(父组件用 @State 配合)
- 代码示例:
// 父组件开联名账户
Parent() {
@State familyAccount: number = 5000
Child({ account: $familyAccount }) // 关键:$ 传递引用
}
// 子组件操作账户
@Component
struct Child {
@Link account: number // 绑定联名账户
build() {
Button("买游戏-100")
.onClick(() => this.account -= 100) // 双方余额实时变化
}
}
4. @Provide/@Consume 跨代通信
-
专业视角
实现跨层级组件数据共享,祖先用@Provide提供数据,后代用@Consume直接消费,任意层级无需中间传递。 -
通俗比喻
相当于「家族公告板」
- 爷爷在客厅贴通知(
@Provide声明)- 所有孙子进门就能看见(
@Consume获取)- 谁修改通知全家同步更新(跨组件双向同步)
- 代码示例:
// 爷爷组件(祖先)
@Component
struct Grandpa {
@Provide familyRule: string = "11点前回家"
}
// 孙子组件(任意后代)
@Component
struct Grandson {
@Consume familyRule: string // 直接看公告板
build() {
Button("修改家规")
.onClick(() => this.familyRule = "12点前回家")
}
}
5. @BuilderParam 动态插槽
-
专业视角
将@Builder函数作为参数传递,实现UI结构的动态注入,常用于容器组件的扩展设计。 -
通俗比喻
相当于「乐高插槽」
- 你造了个空白机器人(容器组件)
- 留出武器插槽(
@BuilderParam)- 别人可以插入激光枪/盾牌(传入不同的
@BuilderUI)
- 代码示例:
// 机器人容器(带插槽)
@Component
struct Robot {
@BuilderParam weaponSlot: () => void // 武器插槽
build() {
Column() {
Image("robot_body.png")
this.weaponSlot() // 这里显示武器
}
}
}
// 组装激光枪机器人
@Builder laserBuilder() {
Image("laser_gun.png")
}
build() {
Robot({ weaponSlot: this.laserBuilder }) // 插入激光枪
}
###🚀 实战场景选择表
| 需求场景 | 推荐方案 | 生活类比 |
|---|---|---|
| 按钮点击计数 | @State |
私人钱包记账 |
| 显示父组件传来的标题 | @Prop |
查看老爸给的零花钱 |
| 实时同步父子表单数据 | @Link |
家庭联名银行卡 |
| 全App切换主题色 | @Provide+@Consume |
家族公告板通知 |
| 封装可自定义内容的卡片 | @BuilderParam |
乐高机器人换武器 |
| 页面间共享用户登录状态 | @StorageLink |
小区物业公告栏 |
###⚠️ 避坑指南
- 循环渲染陷阱
// 错误示范(在build里改状态)
build() {
this.count++ //❌ 引发无限循环
return Text(`${this.count}`)
}
// 正确做法(在事件中修改)
Button("点我").onClick(() => this.count++) // ✅
- 装饰器选用原则
graph LR
A[状态仅自己用] --> |选| B[@State]
C[父传子只读] --> |选| D[@Prop]
E[父子需双向修改] --> |选| F[@Link]
G[全家共享数据] --> |选| H[@Provide]
I[全App共享] --> |选| J[@StorageLink]
- 黄金口诀
自己用 @State
传子用 @Prop
联动用 @Link
全家共享 @Provide
动态UI @BuilderParam
这样结合专业定义和现实比喻,是不是既清晰又实用?开发时对照这个指南,轻松避开鸿蒙的状态管理坑!
更多推荐



所有评论(0)