参考文档 : <HarmonyOS第一课>ArkTS开发语言介绍
@Link 装饰器 参考文档 : https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/arkts-link-0000001524297305-V2
博客源码 : https://download.csdn.net/download/han1202012/89401441
@State 装饰器 修饰的 状态数据 只能绑定 自定义组件 内部的 UI 组件 , 如果要改变 父容器 中的组件 , 就需要使用其它的 装饰器 ,
本篇博客中 介绍的 @Link 装饰器 , 可以 在 子组件 中 使用 @Link 装饰器 绑定 父容器 的 @State 状态数据 ;
在 子组件中 使用 @Link 装饰器 装饰的变量 , 可以和 父容器组件中的 @State 变量 进行双向绑定 ,
父容器 的 @State 变量 和 子组件 @Link 变量 , 不论是哪一方发生了改变 , 都会通知另一方 ;
子组件 中 @Link 装饰 的 变量 如果发生了修改 , 相应绑定的 父容器 中的 @State 装饰的变量 也会发生改变 , 从而触发 父容器 的 build 函数 , 重新渲染 整个父容器 的所有组件 ;
在 子组件 MyComponent 中 , 定义 isSonSelected: boolean 变量 , 使用 @Link 装饰器 修饰 该变量 ;
@Component
export struct MyComponent {
// 子组件中的要关联父容器 @State 状态变量 的 变量
@Link isSonSelected: boolean;
特别注意 : 在 子组件 中 , 不能对 @Link 变量进行初始化 , 否则会报如下错误 ;
Variables decorated by '@Link', '@Consume', and '@ObjectLink' cannot be initialized locally. <ArkTSCheck>
由“@Link”、“@Consume”和“@ObjectLink”修饰的变量不能在本地初始化。< ArkTSCheck >
在 子组件 中的 build 函数中 , 使用该 isSonSelected: boolean 变量 进行 UI 渲染 ,
// 与父容器关联的子组件
Text('子组件 : ' + this.isSonSelected)
.fontSize(20)
.fontColor(this.isSonSelected ? Color.Yellow : Color.White)
.backgroundColor(Color.Black)
.onClick(() => {
if (this.isSonSelected) {
this.isSonSelected = false;
} else {
this.isSonSelected = true;
}
})//onClick(
在父容器中 , 使用 @State 装饰器 修饰 isFatherSelected: boolean 变量 , 这个变量必须初始化 ;
@Entry
@Component
struct Example {
// 父容器中的状态数据
@State isFatherSelected: boolean = false;
特别注意 : 使用 @State 装饰器 修饰的 变量 必须 进行初始化 , 否则会报如下错误 ;
Variables decorated by '@State', '@StorageLink', '@StorageProp', '@LocalStorageLink', '@LocalStorageProp' and '@Provide' must be initialized locally.
由'@State', '@StorageLink', '@StorageProp', '@LocalStorageLink', '@LocalStorageProp'和'@提供'装饰的变量必须在本地初始化。
在 父容器 中 , 创建子组件 ,
如果 子组件 中有 @Link 状态变量 , 则必须在 创建子组件中为 子组件 @Link 变量 设置一个绑定的 父容器的 @State 变量 ;
绑定方法是 在 子组件的 构造函数 中 , 添加 如下参数 , 可以进行 @Link 父容器
{子组件@Link变量: $父容器@State变量}
代码示例如下 :
build() {
// 必须使用布局组件包括子组件
Column(){
// 自定义子组件
MyComponent({isSonSelected: $isFatherSelected});
注意 : 如果子组件中有 @Link 变量 , 那么在 初始化该 子组件 的 构造函数中 , 必须使用 父容器的 @State 变量 绑定该子组件的 @Link 变量 ;
如果 在 子组件 的 构造函数 中 , 没有绑定 @Link 变量 , 则会报如下错误 :
'@Link' decorated 'isSonSelected' must be initialized through the component constructor. <ArkTSCheck>
“@Link”修饰的“isSonSelected”必须通过组件构造函数初始化。< ArkTSCheck >
import hilog from '@ohos.hilog'
@Component
export struct MyComponent {
// 要显示的文字内容
num1: number = 80;
// 循环渲染数据源
numArr: number[] = [9527, 2024, 911];
// 是否被选中
@State isSelected: boolean = false;
// 子组件中的要关联父容器 @State 状态变量 的 变量
@Link isSonSelected: boolean;
// 创建后 , build 之前回调
aboutToAppear() {
console.log("HSL MyComponent aboutToAppear")
}
// 自定义子组件
build() {
Column({ space: 20 }) { // 设置子组件间距为10
// 条件渲染 使用 if else 进行渲染
// 根据不同的条件 动态控制组件显示
if (this.num1 >= 60) {
Text('Text1 ' + this.num1)
.fontSize(20)
.fontColor(Color.White)
.backgroundColor(Color.Red)
} else {
Text('Text1 ' + this.num1)
.fontSize(20)
.fontColor(Color.White)
.backgroundColor(Color.Black)
}
// 第一个参数是数组
// 第二个参数是子组件生成函数
// 第三个参数是键值生成器
ForEach(// 参数一 : 数组, 循环渲染 的 数据源
this.numArr,
// 参数二 : 子组件生成函数
(item: number, index: number): void => {
Text('Text ' + index + " " + item)
.fontSize(20)
.fontColor(Color.White)
.backgroundColor(Color.Black)
}, // (item, index) => {
// 参数三 : 键值生成器, 为组件生成唯一稳定键值
(item: number, index: number): string => "ForEach" + index
) // ForEach
// UI 组件 的 状态管理
Text('选中状态 : ' + this.isSelected)
.fontSize(20)
.fontColor(this.isSelected ? Color.Yellow : Color.White)
.backgroundColor(Color.Black)
.onClick(() => {
if (this.isSelected) {
this.isSelected = false;
} else {
this.isSelected = true;
}
})//onClick(
// 与父容器关联的子组件
Text('子组件 : ' + this.isSonSelected)
.fontSize(20)
.fontColor(this.isSonSelected ? Color.Yellow : Color.White)
.backgroundColor(Color.Black)
.onClick(() => {
if (this.isSonSelected) {
this.isSonSelected = false;
} else {
this.isSonSelected = true;
}
})//onClick(
}
.width('50%') // 设置 Row 的宽度
.height('50%') // 设置 Row 的高度
.backgroundColor(Color.Pink)
.alignItems(HorizontalAlign.Center) // 水平居中
.justifyContent(FlexAlign.Center) // 垂直居中
}
// build 之后 , 销毁前回调
aboutToDisappear() {
console.log("HSL MyComponent aboutToDisappear")
}
}
// 导入外部自定义子组件
import {MyComponent} from '../view/MyComponent';
@Entry
@Component
struct Example {
// 父容器中的状态数据
@State isFatherSelected: boolean = false;
aboutToAppear(){
console.log("HSL Example aboutToAppear")
}
onPageShow() {
console.log("HSL Example onPageShow")
}
onBackPress() {
console.log("HSL Example onBackPress")
}
build() {
// 必须使用布局组件包括子组件
Column(){
// 自定义子组件
MyComponent({isSonSelected: $isFatherSelected});
// 另外的子组件
Text('父容器状态 : ' + this.isFatherSelected)
.fontSize(20)
.fontColor(this.isFatherSelected ? Color.Yellow : Color.White)
.backgroundColor(Color.Black)
}
}
onPageHide() {
console.log("HSL Example onPageHide")
}
aboutToDisappear(){
console.log("HSL Example aboutToDisappear")
}
}
点击 子组件 中的 使用了 @Link 变量 进行渲染的 UI 组件 , 并在该 UI 组件的点击事件中 改变了 @Link 变量的值 ;
改变了子组件 @Link 变量的值 , 则 父容器 中 与之绑定的 @State 变量 也要进行修改 ,
从而 将 父容器 中 使用 @State 变量 进行渲染的 UI 组件 也进行了刷新 ,
最终 点击 子组件 后 , 子组件本身 与 父容器 中的其它组件 都发生了改变 ;
执行效果如下 :
进入界面后 , 默认的状态如下 , 父容器 中的 @State 变量值为 false , 子组件中的 @Link 变量 在 初始化时 , 自动赋值为 父容器 中的 @State 变量的值 , 此时样式如下 :
点击子组件后 , 子组件中的 @Link 变量变为 true , UI 进行重新刷新 ,
相应 绑定的 父容器 @State 变量也变为 true , UI 刷新 , 父容器中的其它子组件发生了相应的改变 ;