鸿蒙Harmony应用开发—ArkTS(@Link装饰器:父子双向同步)

子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。

说明:

从API version 9开始,该装饰器支持在ArkTS卡片中使用。

概述

@Link装饰的变量与其父组件中的数据源共享相同的值。

限制条件

  • @Link装饰器不能在@Entry装饰的自定义组件中使用。

装饰器使用规则说明

@Link变量装饰器说明
装饰器参数
同步类型双向同步。
父组件中@State, @StorageLink和@Link 和子组件@Link可以建立双向数据同步,反之亦然。
允许装饰的变量类型Object、class、string、number、boolean、enum类型,以及这些类型的数组。
支持Date类型。
API11及以上支持Map、Set类型。支持类型的场景请参考观察变化。
API11及以上支持上述支持类型的联合类型,比如string | number, string | undefined 或者 ClassA | null,示例见Link支持联合类型实例。
注意
当使用undefined和null的时候,建议显式指定类型,遵循TypeScipt类型校验,比如:@Link a : string | undefined

支持AkrUI框架定义的联合类型Length、ResourceStr、ResourceColor类型。
类型必须被指定,且和双向绑定状态变量的类型相同。
不支持any。
被装饰变量的初始值无,禁止本地初始化。

变量的传递/访问规则说明

传递/访问说明
从父组件初始化和更新必选。与父组件@State, @StorageLink和@Link 建立双向绑定。允许父组件中@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp装饰变量初始化子组件@Link。
从API version 9开始,@Link子组件从父组件初始化@State的语法为Comp({ aLink: this.aState })。同样Comp({aLink: $aState})也支持。
用于初始化子组件允许,可用于初始化常规变量、@State、@Link、@Prop、@Provide。
是否支持组件外访问私有,只能在所属组件内访问。

图1 初始化规则图示  

zh-cn_image_0000001502092556

观察变化和行为表现

观察变化

  • 当装饰的数据类型为boolean、string、number类型时,可以同步观察到数值的变化,示例请参考简单类型和类对象类型的@Link。

  • 当装饰的数据类型为class或者Object时,可以观察到赋值和属性赋值的变化,即Object.keys(observedObject)返回的所有属性,示例请参考简单类型和类对象类型的@Link。

  • 当装饰的对象是array时,可以观察到数组添加、删除、更新数组单元的变化,示例请参考数组类型的@Link。

  • 当装饰的对象是Date时,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYearsetMonthsetDatesetHourssetMinutessetSecondssetMillisecondssetTimesetUTCFullYearsetUTCMonthsetUTCDatesetUTCHourssetUTCMinutessetUTCSecondssetUTCMilliseconds 更新Date的属性。

@Component
struct DateComponent {@Link selectedDate: Date;build() {Column() {Button(`child increase the year by 1`).onClick(() => {this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1)})Button('child update the new date').margin(10).onClick(() => {this.selectedDate = new Date('2023-09-09')})DatePicker({start: new Date('1970-1-1'),end: new Date('2100-1-1'),selected: this.selectedDate})}}
}@Entry
@Component
struct ParentComponent {@State parentSelectedDate: Date = new Date('2021-08-08');build() {Column() {Button('parent increase the month by 1').margin(10).onClick(() => {this.parentSelectedDate.setMonth(this.parentSelectedDate.getMonth() + 1)})Button('parent update the new date').margin(10).onClick(() => {this.parentSelectedDate = new Date('2023-07-07')})DatePicker({start: new Date('1970-1-1'),end: new Date('2100-1-1'),selected: this.parentSelectedDate})DateComponent({ selectedDate:this.parentSelectedDate })}}
}
  • 当装饰的变量是Map时,可以观察到Map整体的赋值,同时可通过调用Map的接口setcleardelete 更新Map的值。详见装饰Map类型变量。

  • 当装饰的变量是Set时,可以观察到Set整体的赋值,同时可通过调用Set的接口addcleardelete 更新Set的值。详见装饰Set类型变量。

框架行为

@Link装饰的变量和其所属的自定义组件共享生命周期。

为了了解@Link变量初始化和更新机制,有必要先了解父组件和拥有@Link变量的子组件的关系,初始渲染和双向更新的流程(以父组件为@State为例)。

  1. 初始渲染:执行父组件的build()函数后将创建子组件的新实例。初始化过程如下:

    1. 必须指定父组件中的@State变量,用于初始化子组件的@Link变量。子组件的@Link变量值与其父组件的数据源变量保持同步(双向数据同步)。
    2. 父组件的@State状态变量包装类通过构造函数传给子组件,子组件的@Link包装类拿到父组件的@State的状态变量后,将当前@Link包装类this指针注册给父组件的@State变量。
  2. @Link的数据源的更新:即父组件中状态变量更新,引起相关子组件的@Link的更新。处理步骤:

    1. 通过初始渲染的步骤可知,子组件@Link包装类把当前this指针注册给父组件。父组件@State变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(比如@Link包装类)。
    2. 通知@Link包装类更新后,子组件中所有依赖@Link状态变量的系统组件(elementId)都会被通知更新。以此实现父组件对子组件的状态数据同步。
  3. @Link的更新:当子组件中@Link更新后,处理步骤如下(以父组件为@State为例):

    1. @Link更新后,调用父组件的@State包装类的set方法,将更新后的数值同步回父组件。
    2. 子组件@Link和父组件@State分别遍历依赖的系统组件,进行对应的UI的更新。以此实现子组件@Link同步回父组件@State。

使用场景

简单类型和类对象类型的@Link

以下示例中,点击父组件ShufflingContainer中的“Parent View: Set yellowButton”和“Parent View: Set GreenButton”,可以从父组件将变化同步给子组件。

1.点击子组件GreenButton和YellowButton中的Button,子组件会发生相应变化,将变化同步给父组件。因为@Link是双向同步,会将变化同步给@State。

2.当点击父组件ShufflingContainer中的Button时,@State变化,也会同步给@Link,子组件也会发生对应的刷新。

class GreenButtonState {width: number = 0;constructor(width: number) {this.width = width;}
}@Component
struct GreenButton {@Link greenButtonState: GreenButtonState;build() {Button('Green Button').width(this.greenButtonState.width).height(40).backgroundColor('#64bb5c').fontColor('#FFFFFF,90%').onClick(() => {if (this.greenButtonState.width < 700) {// 更新class的属性,变化可以被观察到同步回父组件this.greenButtonState.width += 60;} else {// 更新class,变化可以被观察到同步回父组件this.greenButtonState = new GreenButtonState(180);}})}
}@Component
struct YellowButton {@Link yellowButtonState: number;build() {Button('Yellow Button').width(this.yellowButtonState).height(40).backgroundColor('#f7ce00').fontColor('#FFFFFF,90%').onClick(() => {// 子组件的简单类型可以同步回父组件this.yellowButtonState += 40.0;})}
}@Entry
@Component
struct ShufflingContainer {@State greenButtonState: GreenButtonState = new GreenButtonState(180);@State yellowButtonProp: number = 180;build() {Column() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {// 简单类型从父组件@State向子组件@Link数据同步Button('Parent View: Set yellowButton').width(312).height(40).margin(12).fontColor('#FFFFFF,90%').onClick(() => {this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 40 : 100;})// class类型从父组件@State向子组件@Link数据同步Button('Parent View: Set GreenButton').width(312).height(40).margin(12).fontColor('#FFFFFF,90%').onClick(() => {this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100;})// class类型初始化@LinkGreenButton({ greenButtonState: $greenButtonState }).margin(12)// 简单类型初始化@LinkYellowButton({ yellowButtonState: $yellowButtonProp }).margin(12)}}}
}

Video-link-UsageScenario-one

数组类型的@Link

@Component
struct Child {@Link items: number[];build() {Column() {Button(`Button1: push`).margin(12).width(312).height(40).fontColor('#FFFFFF,90%').onClick(() => {this.items.push(this.items.length + 1);})Button(`Button2: replace whole item`).margin(12).width(312).height(40).fontColor('#FFFFFF,90%').onClick(() => {this.items = [100, 200, 300];})}}
}@Entry
@Component
struct Parent {@State arr: number[] = [1, 2, 3];build() {Column() {Child({ items: $arr }).margin(12)ForEach(this.arr,(item: number) => {Button(`${item}`).margin(12).width(312).height(40).backgroundColor('#11a2a2a2').fontColor('#e6000000')},(item: ForEachInterface) => item.toString())}}
}

Video-link-UsageScenario-two

上文所述,ArkUI框架可以观察到数组元素的添加,删除和替换。在该示例中@State和@Link的类型是相同的number[],不允许将@Link定义成number类型(@Link item : number),并在父组件中用@State数组中每个数据项创建子组件。如果要使用这个场景,可以参考@Prop和@Observed。

装饰Map类型变量

说明:

从API version 11开始,@Link支持Map类型。

在下面的示例中,value类型为Map<number, string>,点击Button改变message的值,视图会随之刷新。

@Component
struct Child {@Link value: Map<number, string>build() {Column() {ForEach(Array.from(this.value.entries()), (item: [number, string]) => {Text(`${item[0]}`).fontSize(30)Text(`${item[1]}`).fontSize(30)Divider()})Button('child init map').onClick(() => {this.value = new Map([[0, "a"], [1, "b"], [3, "c"]])})Button('child set new one').onClick(() => {this.value.set(4, "d")})Button('child clear').onClick(() => {this.value.clear()})Button('child replace the first one').onClick(() => {this.value.set(0, "aa")})Button('child delete the first one').onClick(() => {this.value.delete(0)})}}
}@Entry
@Component
struct MapSample2 {@State message: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]])build() {Row() {Column() {Child({ value: this.message })}.width('100%')}.height('100%')}
}

装饰Set类型变量

说明:

从API version 11开始,@Link支持Set类型。

在下面的示例中,message类型为Set<number>,点击Button改变message的值,视图会随之刷新。

@Component
struct Child {@Link message: Set<number>build() {Column() {ForEach(Array.from(this.message.entries()), (item: [number, string]) => {Text(`${item[0]}`).fontSize(30)Divider()})Button('init set').onClick(() => {this.message = new Set([0, 1, 2, 3, 4])})Button('set new one').onClick(() => {this.message.add(5)})Button('clear').onClick(() => {this.message.clear()})Button('delete the first one').onClick(() => {this.message.delete(0)})}.width('100%')}
}@Entry
@Component
struct SetSample1 {@State message: Set<number> = new Set([0, 1, 2, 3, 4])build() {Row() {Column() {Child({ message: this.message })}.width('100%')}.height('100%')}
}

Link支持联合类型实例

@Link支持联合类型和undefined和null,在下面的示例中,name类型为string | undefined,点击父组件Index中的Button改变name的属性或者类型,Child中也会对应刷新。

@Component
struct Child {@Link name: string | undefinedbuild() {Column() {Button('Child change name to Bob').onClick(() => {this.name = "Bob"})Button('Child change animal to undefined').onClick(() => {this.name = undefined})}.width('100%')}
}@Entry
@Component
struct Index {@State name: string | undefined = "mary"build() {Column() {Text(`The name is  ${this.name}`).fontSize(30)Child({ name: this.name })Button('Parents change name to Peter').onClick(() => {this.name = "Peter"})Button('Parents change name to undefined').onClick(() => {this.name = undefined})}}
}

常见问题

@Link装饰状态变量类型错误

在子组件中使用@Link装饰状态变量需要保证该变量与数据源类型完全相同,且该数据源需为被诸如@State等装饰器装饰的状态变量。

【反例】

@Observed
class ClassA {public c: number = 0;constructor(c: number) {this.c = c;}
}@Component
struct LinkChild {@Link testNum: number;build() {Text(`LinkChild testNum ${this.testNum}`)}
}@Entry
@Component
struct Parent {@State testNum: ClassA[] = [new ClassA(1)];build() {Column() {Text(`Parent testNum ${this.testNum[0].c}`).onClick(() => {this.testNum[0].c += 1;})// @Link装饰的变量需要和数据源@State类型一致LinkChild({ testNum: this.testNum[0].c })}}
}

@Link testNum: number从父组件的LinkChild({testNum:this.testNum.c})初始化。@Link的数据源必须是装饰器装饰的状态变量,简而言之,@Link装饰的数据必须和数据源类型相同,比如@Link: T和@State : T。所以,这里应该改为@Link testNum: ClassA,从父组件初始化的方式为LinkChild({testNum: $testNum})

【正例】

@Observed
class ClassA {public c: number = 0;constructor(c: number) {this.c = c;}
}@Component
struct LinkChild {@Link testNum: ClassA[];build() {Text(`LinkChild testNum ${this.testNum[0]?.c}`)}
}@Entry
@Component
struct Parent {@State testNum: ClassA[] = [new ClassA(1)];build() {Column() {Text(`Parent testNum ${this.testNum[0].c}`).onClick(() => {this.testNum[0].c += 1;})// @Link装饰的变量需要和数据源@State类型一致LinkChild({ testNum: $testNum })}}
}

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/765923.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优化选址问题 | 模拟退火算法求解物流选址问题含Matlab源码

目录 问题代码问题 模拟退火算法(Simulated Annealing, SA)是一种概率性的全局优化算法,用于求解大规模组合优化问题。在物流选址问题中,模拟退火算法可以用来寻找成本最低、效率最高的仓库或配送中心位置。下面是一个简化的模拟退火算法求解物流选址问题的描述,并附带有…

贪吃蛇(C语言超详细版)

目录 前言&#xff1a; 总览&#xff1a; API&#xff1a; 控制台程序&#xff08;Console&#xff09;&#xff1a; 设置坐标&#xff1a; COORD&#xff1a; GetStdHandle&#xff1a; STD_OUTPUT_HANDLE参数&#xff1a; SetConsoleCursorPosition&#xff1a; …

LabVIEW飞行器螺旋桨性能测试与数据监控

LabVIEW飞行器螺旋桨性能测试与数据监控 开发LabVIEW的电动飞行器螺旋桨性能测试与数据监控系统&#xff0c;专门针对电动飞行器螺旋桨在运行过程中的性能测试和监控需求。通过采集转速、转矩、拉力和温度等关键参数&#xff0c;系统能够实时监测和分析螺旋桨的状态&#xff0…

33-Java服务定位器模式 (Service Locator Pattern)

Java服务定位器模式 实现范例 服务定位器模式&#xff08;Service Locator Pattern&#xff09;用于想使用 JNDI 查询定位各种服务的时候考虑到为某个服务查找 JNDI 的代价很高&#xff0c;服务定位器模式充分利用了缓存技术在首次请求某个服务时&#xff0c;服务定位器在 JNDI…

Mysql---备份恢复

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.Mysql日志类型 错误日志&#xff1a; 错误日志主要记录如下几种日志&#xff1a; 服务器启动和关闭过程中的信息 服务器运行过程中的错误信息 事件调度器运行一个时间是产生的信息 在从服…

【大数据】五、yarn基础

Yarn Yarn 是用来做分布式系统中的资源协调技术 MapReduce 1.x 对于 MapReduce 1.x 的版本上&#xff1a; 由 Client 发起计算请求&#xff0c;Job Tracker 接收请求之后分发给各个TaskTrack进行执行 在这个阶段&#xff0c;资源的管理与请求的计算是集成在 mapreduce 上的…

基于java+springboot+vue实现的外卖平台系统(文末源码+Lw+ppt)23-568

摘 要 伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对外卖平台系统进行规范而严格是十分有必要的&#xff0c;所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套外卖平台系统&#xff0c;帮助商家进…

Vulnhub靶机:HackLAB_Vulnix

一、介绍 运行环境&#xff1a;Virtualbox(攻击机)和VMware(靶机) 攻击机&#xff1a;kali&#xff08;192.168.56.101&#xff09; 靶机&#xff1a;HackLAB: Vulnix&#xff08;192.168.56.110&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#x…

2024年阿里云优惠活动整理_云服务器活动大全

2024阿里云优惠活动大全包括云服务器优惠价格、优惠券免费领取入口、域名优惠口令、域名优惠、云数据库优惠活动、对象存储OSS优惠活动、企业邮箱优惠、阿里云建站优惠、无影云电脑优惠价格、CDN特惠等&#xff0c;阿里云服务器网aliyunfuwuqi.com长期更新阿里云优惠活动大全&a…

uniapp套壳打包成apk

不管是vue项目还是uniapp项目,只要能打包成 index.html都可以通过uniapp打包成apk 1.首先把这个项目发布到线上 拿百度举例: 发布到百度服务器用 www.baidu.com能访问到 2.然后到uniapp上发布项目用默认的 vue2,如果你的项目是vue3也用vue2 3.废话我觉得说太多了,直接…

C++项目 -- 负载均衡OJ(一)compile_server

C项目 – 负载均衡OJ&#xff08;二&#xff09;compile_server 文章目录 C项目 -- 负载均衡OJ&#xff08;二&#xff09;compile_server一、compile_server设计1.总体服务流程 二、compiler.hpp三、runner.hpp四、compile_run.hpp五、compile_server.cc5.1.编译功能调试&…

【十二】【算法分析与设计】滑动窗口(3)

30. 串联所有单词的子串 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab","cd","ef"]&#xff…

【计算机视觉】Gaussian Splatting源码解读补充(二)

第一部分 本文是对学习笔记之——3D Gaussian Splatting源码解读的补充&#xff0c;并订正了一些错误。 目录 三、相机相关scene/cameras.py&#xff1a;class Camera 四、前向传播&#xff08;渲染&#xff09;&#xff1a;submodules/diff-gaussian-rasterization/cuda_rast…

schweizer-electronic 公司 safedat2 操作使用说明

schweizer-electronic 公司 safedat2 操作使用说明

基于Java中的SSM框架实现矿场仓储管理系统项目【项目源码+论文说明】

基于Java中的SSM框架实现矿场仓储管理系统演示 摘要 随着数字化的建设&#xff0c;根据当时的发展和用户的需求&#xff0c;选择使用矿产资源管理的信息都是可以用作示范。物质生活已经达到了人们的基本要求&#xff0c;人们追求生活层次越来越高&#xff0c;享受生活成为人们…

Element Plus 基本使用

一、概述 1.1介绍 Element Plus 基本使用 element-ui 是基于vue 开发的一套ui组件库&#xff0c;提供丰富的网页开发组件&#xff0c;可用快速开发网站&#xff0c;降低前端开发成本版本 element目前有两个版本 element-ui&#xff1a;基于vue2element-plus: 基于vue3 官网地址…

机器学习:智能时代的核心引擎

目录 一、什么是机器学习 二、监督学习 三、无监督学习 四、半监督学习 五、强化学习 一、什么是机器学习 机器学习是人工智能的一个分支&#xff0c;它主要基于计算机科学&#xff0c;旨在使计算机系统能够自动地从经验和数据中进行学习并改进&#xff0c;而无需进行明确…

【数据结构】猛猛干7道链表OJ

前言知识点 链表的调试技巧 int main() {struct ListNode* n1(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3(struct ListNode*)malloc(sizeof(struc…

从零开始学习在VUE3中使用canvas(六):lineCap(线条端点样式)

一、简介 lineCap能够让我们设置线条的端点样式&#xff0c;例如 1. butt const ctx canvas.getContext("2d");ctx.lineCap "butt"; // 默认样式&#xff0c;也可以显式指定 2.round const ctx canvas.getContext("2d");//圆头ctx.lineCap …

阿里云服务器“镜像”操作系统选择方法(超详细)

阿里云服务器镜像怎么选择&#xff1f;云服务器操作系统镜像分为Linux和Windows两大类&#xff0c;Linux可以选择Alibaba Cloud Linux&#xff0c;Windows可以选择Windows Server 2022数据中心版64位中文版&#xff0c;阿里云服务器网aliyunfuwuqi.com来详细说下阿里云服务器操…