这是一个使用鸿蒙技术开发的本地原生记账应用,非常适合大家用来练手。相关源码已上传至 Github,点击此处查看项目。欢迎大家交流、指正,也欢迎提交 PR。
一、引言
在鸿蒙(HarmonyOS)应用开发中,ArkTS 提供了丰富的状态管理装饰器,用于处理组件间的数据同步。其中,@Link 装饰器是实现父子组件双向数据绑定 的核心工具。本文将深入讲解 @Link 的工作原理、核心规则,并通过完整的示例代码演示其在实际开发中的应用。
二、@Link 装饰器:父子双向同步
@Link 是 ArkTS 中用于实现父子组件双向数据绑定的状态管理装饰器。它允许子组件中被 @Link 装饰的变量与父组件中的数据源建立双向同步,当其中一方改变时,另一方也会自动更新。
2.1 核心规则
- 同步类型:双向同步
- 允许装饰的类型 :
Object、class、string、number、boolean、enum、Date(API 10+),以及这些类型的数组 - 初始化要求:禁止本地初始化,必须从父组件传入
- 不支持 :
Function类型
2.2 示例代码
typescript
@Entry
@Component
struct ParentComponent {
@State count: number = 0;
@State selected: boolean = false;
build() {
Column({ space: 16 }) {
Text(`父组件 Count: ${this.count}`)
Text(`父组件 Selected: ${this.selected}`)
Button('父组件+1').onClick(() => this.count++)
Divider()
Text('@Link 双向绑定:').fontWeight(FontWeight.Bold)
LinkChild({ count: $count, selected: $selected })
}
.width('100%')
.padding(16)
}
}
@Component
struct LinkChild {
@Link count: number;
@Link selected: boolean;
build() {
Column({ space: 8 }) {
Row({ space: 8 }) {
Text(`子组件 Count: ${this.count}`)
Button('子组件+1').onClick(() => {
this.count++; // 会同步到父组件
})
}
Row({ space: 8 }) {
Text('开关状态')
Toggle({ type: ToggleType.Switch, isOn: this.selected })
.onChange((isOn: boolean) => {
this.selected = isOn; // 会同步到父组件
})
}
}
.padding(12)
.backgroundColor('#E8F4FD')
.borderRadius(8)
}
}
运行效果:

运行效果分析:
- 初始状态 :页面加载时,父组件
count为 0、selected为false,子组件同步显示相同值,开关处于关闭状态。 - 父组件操作 :点击「父组件+1」按钮,父组件
count自增,子组件Count文本同步更新,验证了@Link的双向绑定特性。 - 子组件操作 :
- 点击「子组件+1」按钮,子组件
count++后,父组件Count文本同步变为新值,说明子组件修改@Link变量会反向同步到父组件。 - 切换开关状态,
selected在子组件内更新后,父组件Selected文本立即反映变化,开关状态在父子组件间保持一致。
- 点击「子组件+1」按钮,子组件
- 关键结论 :
@Link实现了真正的双向同步------无论数据在父组件还是子组件中修改,双方都会自动更新,无需手动传递回调函数或事件。
2.3 使用要点
- 父组件通过
$语法 (如$count)或直接传递变量给子组件的@Link变量 - 子组件内修改
@Link变量会自动同步回父组件,无需手动回调 - 适用于需要子组件修改后影响父组件的场景,如表单编辑、状态切换等
- 对于更复杂的嵌套对象变化,推荐结合
@Observed装饰器与@ObjectLink使用
三、进阶用法:对象类型与数组
当 @Link 装饰的对象或数组类型时,同样支持双向同步。以下示例演示了如何传递一个对象给子组件。
typescript
@Entry
@Component
struct Parent {
@State user: User = { name: '张三', age: 25 };
build() {
Column() {
Text(`父组件:${this.user.name}, ${this.user.age}岁`)
Child({ user: $user })
}
}
}
@Component
struct Child {
@Link user: User;
build() {
Column() {
Text(`子组件:${this.user.name}, ${this.user.age}岁`)
Button('修改姓名').onClick(() => {
this.user.name = '李四'; // 同步到父组件
})
}
}
}
interface User {
name: string;
age: number;
}
运行效果:

运行效果分析:
- 初始状态 :页面加载时,父组件
user对象为{ name: '张三', age: 25 },子组件同步显示相同信息,验证了@Link对对象类型的双向绑定能力。 - 子组件操作 :点击「修改姓名」按钮,子组件将
user.name改为'李四',父组件文本立即同步更新为「李四, 25岁」,说明子组件修改@Link对象的属性会反向同步到父组件。 - 关键结论 :
@Link不仅支持基本类型,对对象类型 同样实现双向同步------子组件修改对象的任意属性后,父组件中对应的@State变量也会自动更新,无需手动触发刷新或传递回调。
四、注意事项与最佳实践
- 避免循环依赖:确保父子组件之间的数据流是清晰的,避免在多个层级间形成复杂的循环绑定。
- 性能考虑 :对于频繁变化的数据,合理使用
@Link,避免不必要的全量渲染。 - 类型安全 :父组件传递的变量类型必须与子组件
@Link声明的类型完全一致。 - 替代方案 :对于简单的单向数据流,优先使用
@Prop;对于跨多级组件的状态共享,考虑使用@Provide与@Consume。
五、总结
@Link 装饰器是鸿蒙应用开发中实现父子组件双向数据绑定的利器。通过 $ 语法传递状态,子组件可以安全地修改父组件的数据,极大地简化了表单编辑、状态切换等交互场景的开发。
掌握 @Link 的使用,将帮助你更高效地构建响应式、可维护的鸿蒙应用。