首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

鸿蒙HarmonyOS开发框架—学习ArkTS语言(状态管理 三)

  • 25-02-22 03:20
  • 2174
  • 10952
blog.csdn.net

@Link装饰器:父子双向同步

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

概述

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

装饰器使用规则说明

@Link变量装饰器

说明

装饰器参数

无

同步类型

双向同步。 父组件中@State, @StorageLink和@Link 和子组件@Link可以建立双向数据同步,反之亦然。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。 类型必须被指定,且和双向绑定状态变量的类型相同。 不支持any,不支持简单类型和复杂类型的联合类型,不允许使用undefined和null。 说明 不支持Length、ResourceStr、ResourceColor类型,Length、ResourceStr、ResourceColor为简单类型和复杂类型的联合类型。

被装饰变量的初始值

无,禁止本地初始化。

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

传递/访问

说明

从父组件初始化和更新

必选。与父组件@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 初始化规则图示

观察变化和行为表现
观察变化
  • 当装饰的数据类型为boolean、string、number类型时,可以同步观察到数值的变化。
  • 当装饰的数据类型为class或者Object时,可以观察到赋值和属性赋值的变化,即Object.keys(observedObject)返回的所有属性。
  • 当装饰的对象是array时,可以观察到数组添加、删除、更新数组单元的变化。
框架行为

@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”,可以从父组件将变化同步给子组件,子组件GreenButton和YellowButton中@Link装饰变量的变化也会同步给其父组件。

  1. class GreenButtonState {
  2. width: number = 0;
  3. constructor(width: number) {
  4. this.width = width;
  5. }
  6. }
  7. @Component
  8. struct GreenButton {
  9. @Link greenButtonState: GreenButtonState;
  10. build() {
  11. Button('Green Button')
  12. .width(this.greenButtonState.width)
  13. .height(150.0)
  14. .backgroundColor('#00ff00')
  15. .onClick(() => {
  16. if (this.greenButtonState.width < 700) {
  17. // 更新class的属性,变化可以被观察到同步回父组件
  18. this.greenButtonState.width += 125;
  19. } else {
  20. // 更新class,变化可以被观察到同步回父组件
  21. this.greenButtonState = new GreenButtonState(100);
  22. }
  23. })
  24. }
  25. }
  26. @Component
  27. struct YellowButton {
  28. @Link yellowButtonState: number;
  29. build() {
  30. Button('Yellow Button')
  31. .width(this.yellowButtonState)
  32. .height(150.0)
  33. .backgroundColor('#ffff00')
  34. .onClick(() => {
  35. // 子组件的简单类型可以同步回父组件
  36. this.yellowButtonState += 50.0;
  37. })
  38. }
  39. }
  40. @Entry
  41. @Component
  42. struct ShufflingContainer {
  43. @State greenButtonState: GreenButtonState = new GreenButtonState(300);
  44. @State yellowButtonProp: number = 100;
  45. build() {
  46. Column() {
  47. // 简单类型从父组件@State向子组件@Link数据同步
  48. Button('Parent View: Set yellowButton')
  49. .onClick(() => {
  50. this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 100 : 100;
  51. })
  52. // class类型从父组件@State向子组件@Link数据同步
  53. Button('Parent View: Set GreenButton')
  54. .onClick(() => {
  55. this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100;
  56. })
  57. // class类型初始化@Link
  58. GreenButton({ greenButtonState: $greenButtonState })
  59. // 简单类型初始化@Link
  60. YellowButton({ yellowButtonState: $yellowButtonProp })
  61. }
  62. }
  63. }

复制

 数组类型的@Link

  1. @Component
  2. struct Child {
  3. @Link items: number[];
  4. build() {
  5. Column() {
  6. Button(`Button1: push`).onClick(() => {
  7. this.items.push(this.items.length + 1);
  8. })
  9. Button(`Button2: replace whole item`).onClick(() => {
  10. this.items = [100, 200, 300];
  11. })
  12. }
  13. }
  14. }
  15. @Entry
  16. @Component
  17. struct Parent {
  18. @State arr: number[] = [1, 2, 3];
  19. build() {
  20. Column() {
  21. Child({ items: $arr })
  22. ForEach(this.arr,
  23. item => {
  24. Text(`${item}`)
  25. },
  26. item => item.toString()
  27. )
  28. }
  29. }
  30. }

复制

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

@Provide装饰器和@Consume装饰器:与后代组件双向同步

@Provide和@Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递。

其中@Provide装饰的变量是在祖先节点中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费(绑定)”祖先节点提供的变量。

概述

@Provide/@Consume装饰的状态变量有以下特性:

  • @Provide装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide的方便之处在于,开发者不需要多次在组件之间传递变量。
  • 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。
  • @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,变量类型必须相同。
  1. // 通过相同的变量名绑定
  2. @Provide a: number = 0;
  3. @Consume a: number;
  4. // 通过相同的变量别名绑定
  5. @Provide('a') b: number = 0;
  6. @Consume('a') c: number;

复制

装饰器说明

@State的规则同样适用于@Provide,差异为@Provide还作为多层后代的同步源。

@Provide变量装饰器

说明

装饰器参数

别名:常量字符串,可选。 如果指定了别名,则通过别名来绑定变量;如果未指定别名,则通过变量名绑定变量。

同步类型

双向同步。 从@Provide变量到所有@Consume变量以及相反的方向的数据同步。双向同步的操作与@State和@Link的组合相同。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。 不支持any,不支持简单类型和复杂类型的联合类型,不允许使用undefined和null。 必须指定类型。@Provide变量的@Consume变量的类型必须相同。 说明 不支持Length、ResourceStr、ResourceColor类型,Length、ResourceStr、ResourceColor为简单类型和复杂类型的联合类型。

被装饰变量的初始值

必须指定。

@Consume变量装饰器

说明

装饰器参数

别名:常量字符串,可选。 如果提供了别名,则必须有@Provide的变量和其有相同的别名才可以匹配成功;否则,则需要变量名相同才能匹配成功。

同步类型

双向:从@Provide变量(具体请参见@Provide)到所有@Consume变量,以及相反的方向。双向同步操作与@State和@Link的组合相同。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。 不支持any,不允许使用undefined和null。 必须指定类型。@Provide变量的@Consume变量的类型必须相同。 说明 @Consume装饰的变量,在其父节点或者祖先节点上,必须有对应的属性和别名的@Provide装饰的变量。

被装饰变量的初始值

无,禁止本地初始化。

  • @Consume装饰的变量,在其父节点或者祖先节点上,必须有对应的属性和别名的@Provide装饰的变量。

被装饰变量的初始值 无,禁止本地初始化。

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

@Provide传递/访问

说明

从父组件初始化和更新

可选,允许父组件中常规变量、@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp装饰的变量装饰变量初始化子组件@Provide。

用于初始化子组件

允许,可用于初始化@State、@Link、@Prop、@Provide。

和父组件同步

否。

和后代组件同步

和@Consume双向同步。

是否支持组件外访问

私有,仅可以在所属组件内访问。

图1 @Provide初始化规则图示

@Consume传递/访问

说明

从父组件初始化和更新

禁止。通过相同的变量名和alias(别名)从@Provide初始化。

用于初始化子组件

允许,可用于初始化@State、@Link、@Prop、@Provide。

和祖先组件同步

和@Provide双向同步。

是否支持组件外访问

私有,仅可以在所属组件内访问

图2 @Consume初始化规则图示

观察变化和行为表现
观察变化
  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
  • 当装饰的数据类型为class或者Object的时候,可以观察到赋值和属性赋值的变化(属性为Object.keys(observedObject)返回的所有属性)。
  • 当装饰的对象是array的时候,可以观察到数组的添加、删除、更新数组单元。
框架行为
  1. 初始渲染:
    1. @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件;
    2. 子组件中如果使用@Consume变量,则会在map中查找是否有该变量名/alias(别名)对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR;
    3. 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会保存在map中查找到的@Provide变量,并把自己注册给@Provide。
  2. 当@Provide装饰的数据变化时:
    1. 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
    2. 通知@Consume更新后,子组件所有依赖@Consume的系统组件(elementId)都会被通知更新。以此实现@Provide对@Consume状态数据同步。
  3. 当@Consume装饰的数据变化时:
    1. 通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新的数值同步回@Provide,以此实现@Consume向@Provide的同步更新。
使用场景

在下面的示例是与后代组件双向同步状态@Provide和@Consume场景。当分别点击CompA和CompD组件内Button时,reviewVotes 的更改会双向同步在CompA和CompD中。

  1. @Component
  2. struct CompD {
  3. // @Consume装饰的变量通过相同的属性名绑定其祖先组件CompA内的@Provide装饰的变量
  4. @Consume reviewVotes: number;
  5. build() {
  6. Column() {
  7. Text(`reviewVotes(${this.reviewVotes})`)
  8. Button(`reviewVotes(${this.reviewVotes}), give +1`)
  9. .onClick(() => this.reviewVotes += 1)
  10. }
  11. .width('50%')
  12. }
  13. }
  14. @Component
  15. struct CompC {
  16. build() {
  17. Row({ space: 5 }) {
  18. CompD()
  19. CompD()
  20. }
  21. }
  22. }
  23. @Component
  24. struct CompB {
  25. build() {
  26. CompC()
  27. }
  28. }
  29. @Entry
  30. @Component
  31. struct CompA {
  32. // @Provide装饰的变量reviewVotes由入口组件CompA提供其后代组件
  33. @Provide reviewVotes: number = 0;
  34. build() {
  35. Column() {
  36. Button(`reviewVotes(${this.reviewVotes}), give +1`)
  37. .onClick(() => this.reviewVotes += 1)
  38. CompB()
  39. }
  40. }
  41. }

最后,为了能让大家更好的去学习提升鸿蒙 (Harmony OS) 开发技术,小编连夜整理了一份30个G纯血版学习资料(含视频、电子书、学习文档等)以及一份在Github上持续爆火霸榜的《纯血版华为鸿蒙 (Harmony OS)开发手册》(共计890页),希望对大家有所帮助。

纯血版鸿蒙 HarmonyOS 4.0 视频学习资料

 需要以上视频学习资料小伙伴

请点击→纯血版全套鸿蒙HarmonyOS学习资料


《纯血版华为鸿蒙 (Harmony OS)开发手册》

这份手册涵盖了当前鸿蒙 (Harmony OS) 开发技术必掌握的核心知识点

纯血版鸿蒙 (Harmony OS)开发手册部分精彩内容

HarmonyOS 概念:

  • 系统定义
  • 技术架构
  • 技术特性
  • 系统安全

如何快速入门?

  • 基本概念
  • 构建第一个ArkTS应用
  • 构建第一个JS应用
  • ……


开发基础知识: 

  • 应用基础知识
  • 配置文件
  • 应用数据管理
  • 应用安全管理
  • 应用隐私保护
  • 三方应用调用管控机制
  • 资源分类与访问
  • 学习ArkTS语言
  • ……

基于ArkTS 开发:

  • Ability开发
  • UI开发
  • 公共事件与通知
  • 窗口管理
  • 媒体
  • 安全
  • 网络与链接
  • 电话服务
  • 数据管理
  • 后台任务(Background Task)管理
  • 设备管理
  • 设备使用信息统计
  • DFX
  • 国际化开发
  • 折叠屏系列
  • .……

获取以上文中提到的这份纯血版鸿蒙 (Harmony OS) 开发资料的小伙伴 

请点击→纯血版全套鸿蒙HarmonyOS学习资料


?写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新VIP学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

最新鸿蒙Next全套学习资料请扫码
微信名片
注:本文转载自blog.csdn.net的蜀道山QAQ的文章"https://blog.csdn.net/shudaoshanQAQ/article/details/135612472"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top