【成长纪实】ArkTS V1 装饰器总结
ArkTS V1 装饰器核心摘要 ArkTS V1 装饰器是华为方舟框架的状态管理系统,通过声明式语法实现数据驱动UI更新。主要包含: 组件状态装饰器: @State:组件私有状态 @Prop:父→子单向传递 @Link:父子双向绑定 @Provide/@Consume:跨级组件数据共享 特殊功能装饰器: @Watch:监听状态变化 @BuilderParam:支持UI插槽 LocalStorag
·
ArkTS V1 装饰器总结
📌 快速概览
V1 装饰器是 ArkTS 的状态管理系统,通过装饰器语法实现数据驱动 UI 更新。
核心理念:数据驱动 UI、声明式开发、分层管理
🎯 装饰器体系
V1装饰器体系
├─ 组件状态装饰器
│ ├─ @State ─── 组件内部状态
│ ├─ @Prop ─── 父到子单向传递
│ ├─ @Link ─── 父子双向绑定
│ ├─ @Provide ─── 向后代提供数据
│ ├─ @Consume ─── 从祖先获取数据
│ ├─ @Observed ─── 标记类可观察
│ └─ @ObjectLink ─── 深度观察对象
│
├─ 监听装饰器
│ └─ @Watch ─── 监听状态变化
│
├─ 构建装饰器
│ └─ @BuilderParam ─── 自定义UI构建
│
└─ 存储装饰器
├─ LocalStorage ─── 页面级存储
└─ AppStorage ─── 应用级存储
📖 组件状态装饰器
@State - 组件内部状态
作用:定义组件的私有状态,状态变化触发 UI 更新。
特点:
- 只能在组件内部使用,外部无法传入
- 必须初始化
- 浅观察:只能监听第一层属性变化(对象的嵌套属性变化不会触发更新)
使用场景:
- 计数器、开关状态、表单输入等组件内部状态
- 不需要与其他组件共享的数据
示例:
@State count: number = 0 // ✅ 基本类型
@State list: string[] = [] // ✅ 数组
@State user: { name: string } = { name: '张三' } // ✅ 对象
// ✅ 能触发更新
this.count = 100
this.list.push('新元素')
this.user = { name: '李四' }
// ❌ 不能触发更新(浅观察)
this.user.name = '李四' // 第二层属性
@Prop - 父到子单向传递
作用:从父组件传递数据到子组件,子组件只能读取,不能修改父组件的数据。
特点:
- 单向数据流:父 → 子
- 值传递(深拷贝),子组件修改不影响父组件
- 可选初始化(可设置默认值)
使用场景:
- 子组件只需要展示父组件的数据,不需要修改
- 配置型组件(如标题、颜色、尺寸等属性)
示例:
// 父组件
@State message: string = 'Hello'
ChildComponent({ message: this.message })
// 子组件
@Prop message: string = '默认值' // 可选默认值
// 子组件修改只影响自己,不影响父组件
this.message = 'World' // ❌ 不影响父组件
@Link - 父子双向绑定
作用:父子组件共享同一份数据,任意一方修改都会同步更新。
特点:
- 双向数据流:父 ↔ 子
- 引用传递,父子共享同一个数据
- 使用
$语法传递 - 不能初始化,必须由父组件传入
- 浅观察
使用场景:
- 表单输入:子组件修改需要同步到父组件
- 开关状态:父子组件都需要修改和读取
- 简单的父子数据共享
示例:
// 父组件
@State count: number = 0
ChildComponent({ count: $count }) // 使用 $ 语法
// 子组件
@Link count: number // 不能初始化
// 父子任一方修改,都会同步
this.count++ // ✅ 父子同步更新
@Provide / @Consume - 跨级传递
作用:实现跨多级组件的数据传递,无需逐层传递。
特点:
- 祖先组件用
@Provide提供数据 - 后代组件用
@Consume消费数据 - 双向绑定:后代修改会同步到祖先
- 通过相同变量名或别名关联
使用场景:
- 主题配置:根组件提供主题,所有子孙组件都能访问
- 用户信息:登录后的用户信息全局共享
- 多层嵌套组件间的数据共享
示例:
// 祖先组件
@Provide count: number = 0
// 或使用别名
@Provide('theme') currentTheme: string = 'light'
// 后代组件(中间层无需传递)
@Consume count: number
@Consume('theme') theme: string
// 后代修改会同步到祖先
this.count++ // ✅ 祖先同步更新
@Observed / @ObjectLink - 深度观察
作用:实现对象嵌套属性的深度观察,解决 @State/@Link 只能观察第一层的问题。
特点:
@Observed:装饰类,使类实例可被观察@ObjectLink:装饰变量,接收可观察对象- 深度观察:对象任意层级的属性变化都能触发更新
- 双向绑定
- 必须配合使用
使用场景:
- 复杂对象:用户信息、商品详情等多层嵌套对象
- 列表项:数组中的对象需要单独传递给子组件
- 购物车、表单等需要修改嵌套属性的场景
示例:
// 1. 定义类,加 @Observed
@Observed
class Person {
name: string
age: number
}
// 2. 父组件用 @State 持有
@State person: Person = new Person('张三', 25)
// 3. 传递给子组件
ChildComponent({ person: this.person })
// 4. 子组件用 @ObjectLink 接收
@ObjectLink person: Person
// ✅ 嵌套属性变化也能触发更新
this.person.name = '李四' // ✅ 深度观察
this.person.age++ // ✅ 深度观察
🔍 监听装饰器
@Watch - 监听状态变化
作用:监听状态变量的变化,在变化时执行自定义回调函数。
特点:
- 可监听 @State、@Prop、@Link 等装饰的变量
- 状态变化后自动执行回调
- 适合执行副作用操作
使用场景:
- 表单验证:输入变化时实时验证
- 数据联动:价格或数量变化时自动计算总价
- 本地存储:状态变化时自动保存到本地
- 日志记录:记录状态变化历史
示例:
@State @Watch('onCountChange') count: number = 0
onCountChange() {
console.log(`count 变化了: ${this.count}`)
// 执行验证、保存、计算等操作
}
🏗️ 构建装饰器
@BuilderParam - 自定义 UI 构建
作用:允许父组件向子组件传递自定义 UI 构建函数,实现插槽功能。
特点:
- 提高组件复用性
- 支持传递带参数的构建函数
- 可设置默认 UI
使用场景:
- 卡片组件:自定义卡片内容
- 对话框:自定义头部、内容、底部
- 列表组件:自定义列表项渲染
- 容器组件:需要自定义子内容的场景
示例:
// 子组件
@Component
struct Card {
@BuilderParam content: () => void
build() {
Column() {
Text('卡片标题')
this.content() // 渲染父组件传入的UI
}
}
}
// 父组件
@Builder myContent() {
Text('自定义内容')
Button('自定义按钮')
}
Card({ content: this.myContent })
💾 存储装饰器
LocalStorage - 页面级存储
作用:页面级的共享状态,同一页面内的组件共享数据。
装饰器:
@LocalStorageLink:双向绑定,组件修改会同步到 LocalStorage@LocalStorageProp:单向绑定,只读,修改不影响 LocalStorage
使用场景:
- 页面内多个组件共享的临时数据
- 页面级配置(如筛选条件、显示模式)
- 不需要跨页面共享的数据
示例:
// 创建 LocalStorage 实例
const storage = new LocalStorage({ count: 0 })
@Entry(storage)
@Component
struct Page {
@LocalStorageLink('count') count: number = 0 // 双向
@LocalStorageProp('count') readCount: number = 0 // 单向只读
}
AppStorage - 应用级存储
作用:应用级的全局共享状态,所有页面都可以访问。
装饰器:
@StorageLink:双向绑定,修改会全局同步@StorageProp:单向绑定,只读
使用场景:
- 用户登录信息(用户名、头像)
- 主题配置(暗黑模式、语言)
- 全局设置(字体大小、通知开关)
- 跨页面共享的数据
示例:
// 初始化全局数据
AppStorage.SetOrCreate('theme', 'light')
// 任意页面使用
@StorageLink('theme') theme: string = 'light' // 双向
@StorageProp('theme') readTheme: string = 'light' // 单向只读
📊 装饰器对比表
组件状态装饰器对比
| 装饰器 | 数据流 | 观察深度 | 初始化 | 典型场景 |
|---|---|---|---|---|
| @State | 组件内部 | 浅(第一层) | 必须 | 组件私有状态 |
| @Prop | 父 → 子(单向) | 浅 | 可选 | 子组件只读数据 |
| @Link | 父 ↔ 子(双向) | 浅 | 不能 | 简单的父子共享数据 |
| @Provide | 祖先 → 后代 | 浅 | 必须 | 跨级数据提供 |
| @Consume | 祖先 ↔ 后代 | 浅 | 不能 | 跨级数据消费 |
| @ObjectLink | 父 ↔ 子(双向) | 深(所有层) | 不能 | 嵌套对象深度观察 |
存储装饰器对比
| 装饰器 | 作用域 | 数据流 | 典型场景 |
|---|---|---|---|
| @LocalStorageLink | 页面级 | 双向 | 页面内组件共享数据 |
| @LocalStorageProp | 页面级 | 单向 | 页面内组件只读数据 |
| @StorageLink | 应用级 | 双向 | 全局共享数据(主题、用户) |
| @StorageProp | 应用级 | 单向 | 全局只读数据(应用配置) |
🎯 选择决策
快速决策树
需要传递数据吗?
├─ 否 → @State(组件内部状态)
│
└─ 是 → 传递给谁?
├─ 子组件
│ ├─ 只读?→ @Prop
│ ├─ 可改?
│ │ ├─ 简单对象 → @Link
│ │ └─ 嵌套对象 → @ObjectLink
│
├─ 跨多级 → @Provide/@Consume
│
└─ 全局共享
├─ 页面内 → LocalStorage
└─ 全应用 → AppStorage
场景选择建议
| 场景 | 推荐装饰器 |
|---|---|
| 计数器、开关 | @State |
| 配置属性(颜色、大小) | @Prop |
| 表单输入 | @Link |
| 用户信息、商品详情 | @ObjectLink |
| 主题配置 | @Provide/@Consume |
| 监听输入验证 | @Watch |
| 自定义列表项 | @BuilderParam |
| 页面筛选条件 | LocalStorage |
| 全局主题、用户信息 | AppStorage |
🎓 核心要点
浅观察 vs 深度观察
浅观察(@State、@Prop、@Link):
- 只能观察第一层属性变化
- 修改嵌套属性不会触发 UI 更新
- 解决方法:整体替换对象或使用 @Observed + @ObjectLink
深度观察(@Observed + @ObjectLink):
- 可以观察任意层级的属性变化
- 需要给类加 @Observed 装饰器
- 嵌套类也需要加 @Observed
记忆口诀
State 组件私有,Prop 单向只读
Link 双向美元,Provide 跨级通
Observed 深观察,Watch 来监听
BuilderParam 插槽,Storage 存全局
📌 V1 vs V2
| 特性 | V1 装饰器 | V2 装饰器(新一代) |
|---|---|---|
| 观察粒度 | 浅观察(第一层) | 精细化观察(属性级) |
| 性能 | 整个对象变化才更新 | 只更新变化的属性 |
| 学习曲线 | 相对简单 | 更复杂但更强大 |
| 适用场景 | 简单状态管理 | 复杂嵌套对象、性能敏感 |
V2 装饰器:
@ObservedV2+@Trace:替代 @Observed/@ObjectLink@Local:替代 @State@Param:替代 @Prop/@Link@Event:事件通信@Monitor:替代 @Watch
📚 总结
核心原则
- 数据驱动:状态变化自动更新 UI
- 单向数据流优先:优先使用 @State + @Prop
- 按需选择:根据场景选择合适的装饰器
- 合理拆分:大组件拆分为小组件,提高复用性
何时使用 V1
✅ 推荐场景:
- 现有项目维护
- 简单的状态管理
- 学习 ArkTS 基础
- 兼容性要求高
⚠️ 考虑 V2 场景:
- 新项目开发
- 复杂的嵌套对象
- 性能敏感应用
- 需要精细化更新
更多推荐



所有评论(0)