本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、@Link装饰器核心概念
1. 本质特性
@Link是ArkUI中实现双向数据绑定的核心装饰器,具有以下核心特性:
- 双向同步:父子组件间的数据实时双向流动
- 引用共享:与父组件共享同一数据源(非拷贝)
- 强类型约束:必须与父组件@State/@Link变量类型严格一致
- 跨组件更新:任一端的修改都会触发关联组件更新
2. 版本演进
| 特性 | API 9 | API 10 | API 11+ |
|---|---|---|---|
| 基础类型支持 | ✓ | ✓ | ✓ |
| Date类型支持 | ✗ | ✓ | ✓ |
| Map/Set支持 | ✗ | ✗ | ✓ |
| 元服务支持 | ✗ | ✗ | ✓ |
| 联合类型支持 | ✗ | ✗ | ✓ |
备注:不支持装饰Function类型。
二、装饰器使用规范
1. 变量类型支持与观察范围
| 类型类别 | 可观察操作 |
|---|---|
| 基本类型 | 赋值操作(=) |
| 对象/类 | 对象整体赋值、一级属性修改(需配合@Observed) |
| 数组 | 数组整体赋值、push/pop/shift/unshift等操作方法 |
| Date | 整体赋值及setXXX方法(setFullYear等) |
| Map | set/clear/delete操作 |
| Set | add/clear/delete操作 |
2. 初始化机制
// 必须从父组件初始化(禁止本地初始化)
@Link value: number;
// 父组件传递方式(使用$建立引用)
ParentComponent({
value: $parentState
})
// API 11+必须初始化场景
@Component
struct Child {
@Require @Link requiredValue: number; // 必须父组件传参
}
备注:禁止本地初始化。允许父组件中装饰变量初始化子组件的@Link,并建立双向绑定。
3. 核心限制说明
关键规则:
- 编译警告:@Link装饰器不建议在@Entry装饰的自定义组件中使用,否则编译时会抛出警告
- 运行时错误:若该自定义组件作为页面根节点使用,则会抛出运行时错误
三、状态同步机制
1. 同步原理
2. 框架行为细节
-
初始渲染阶段:
- 父组件build()创建子组件实例
- 建立双向绑定引用关系
- 初始化子组件@Link变量
-
更新阶段:
- 父组件更新流程:
// 父组件状态变更
this.parentState = newValue
→ 触发父组件重新渲染
→ 更新子组件@Link值
→ 触发子组件UI更新
- 子组件更新流程:
// 子组件修改@Link
this.linkValue = newValue
→ 反向同步到父组件源状态
→ 触发父组件重新渲染
→ 更新所有依赖该状态的组件
四、与@Prop的对比
| 特性 | @Link | @Prop |
|---|---|---|
| 同步方向 | 双向 | 单向(父→子) |
| 数据传递 | 引用传递(共享内存) | 深拷贝(独立副本) |
| 初始化 | 必须父组件传入 | 可本地初始化 |
| 更新范围 | 全链路更新 | 仅子组件内部更新 |
| 内存消耗 | 低(共享引用) | 高(拷贝消耗) |
| 适用场景 | 需要双向控制的表单场景 | 只读数据展示场景 |
五、高级使用技巧
1. 复杂对象绑定
@Observed
class UserProfile {
@Track name: string = '';
@Track age: number = 0;
}
@Entry
@Component
struct Parent {
@State profile: UserProfile = new UserProfile();
build() {
Column() {
// 使用$建立双向绑定
ChildComponent({ profile: $profile })
}
}
}
@Component
struct ChildComponent {
@Link profile: UserProfile;
build() {
Column() {
TextInput({ text: this.profile.name })
.onChange(val => this.profile.name = val) // 双向绑定
Slider({ value: this.profile.age })
.onChange(val => this.profile.age = val) // 双向绑定
}
}
}
2. 数组操作
@Entry
@Component
struct Parent {
@State items: string[] = ['A', 'B', 'C'];
build() {
Column() {
ChildComponent({ items: $items })
Button('Add Item')
.onClick(() => this.items.push('New')) // 支持数组方法
}
}
}
@Component
struct ChildComponent {
@Link items: string[];
build() {
List() {
ForEach(this.items, item => {
ListItem() {
Text(item)
}
})
}
}
}
六、性能优化
1. 嵌套数据结构优化
// 不推荐(超过3层嵌套)
@State deepData: {
layer1: {
layer2: {
layer3: string
}
}
}
// 推荐方案(扁平化结构)
@Observed
class Layer3 {
@Track value: string = '';
}
@State flatData: Layer3 = new Layer3();
2. 渲染优化
@Component
struct OptimizedComponent {
@Link data: LargeDataSet;
build() {
// 使用LazyForEach优化大数据量渲染
LazyForEach(this.data, item => {
ListItem() {
Text(item.key).fontSize(14) // 简化子组件结构
}
})
}
}
2407

被折叠的 条评论
为什么被折叠?



