ArkUI-状态管理-@Provide、@Consume、@Observed、@ObjectLink

2024-09-03 17:20

本文主要是介绍ArkUI-状态管理-@Provide、@Consume、@Observed、@ObjectLink,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ArkUI-状态管理

  • @Provide装饰器和@Consume装饰器:与后代组件双向同步
    • 概述
    • 观察变化
    • 框架行为
    • Provide支持allowOverride参数
  • @Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化
    • 概述
    • 限制条件
    • 观察变化
    • 框架行为

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

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

其中@Provide装饰的变量是在祖先组件中,@Consume装饰的变量是在后代组件中。

概述

@Provide和@Consume装饰的变量有以下特性:

  • @Provide装饰的状态变量自动对其所有的后代组件可用。
  • 后代通过使用@Consume去获取@Provide提供的变量。
  • @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,可能导致应用数据异常。
// 通过相同的变量名绑定
@Provide a: number = 0;
@Consume a: number;// 通过相同的变量别名绑定
@Provide('a') b: number = 0;
@Consume('a') c: number;

@Provide和@Consume通过相同的变量名或者相同的变量别名绑定时,@Provide装饰的变量和@Consume装饰的变量是一对多的关系。不允许在同一个自定义组件内、包括其子组件内生命多个同名或者同别名的@Provide装饰的变量,@Provide的属性名或者别名需要唯一且确定,如果生命多个同名或者同别名的@Provide装饰的变量,会发生运行时错误。

观察变化

  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数据的变化。
  • 当装饰的数据类型为class或者Object的时候,可以观察到赋值和属性赋值的变化。
  • 当装饰的对象是array的时候,可以观察到数组的添加、删除、更新数组单元。
  • 当装饰的对象是Date时,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds 更新Date的属性。
  • 当装饰的变量是Map时,可以观察到Map整体的赋值,同时可通过调用Map的接口set, clear, delete 更新Map的值。
  • 当装饰的变量是Set时,可以观察到Set整体的赋值,同时可通过调用Set的接口add, clear, delete 更新Set的值。

框架行为

  1. 初始渲染:
    • @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件。
    • 子组件如果使用@Consume变量,则会在map中查找是否有该变量名/别名对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR
    • 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会在map中查找对应的@Provide变量进行保存,并把自己注册给@Provide。
  2. 当@Provide装饰的数据发生变化时:
    • 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历所有依赖它的系统㢟和状态变量。
    • 通知@Consume更新后,子组件所有依赖@Consume的系统组件都会被通知更新。
  3. 当@Consume装饰的数据发生变化时:
    通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新值同步回@Provide,以此实现@Consume向@Provide的同步更新。

在这里插入图片描述

Provide支持allowOverride参数

上边我们提到,不允许在同一个自定义组件内、包括其子组件内生命多个同名或者同别名的@Provide装饰的变量,@Provide的属性名或者别名需要唯一且确定,如果生命多个同名或者同别名的@Provide装饰的变量,会发生运行时错误。

如果需要对@Provide装饰的变量进行重写,可以子组件中重写的位置使用allowOverride参数。

@Component
struct GrandSon {// @Consume装饰的变量通过相同的属性名绑定其祖先内的@Provide装饰的变量@Consume("reviewVotes") reviewVotes: number;build() {Column() {Text(`reviewVotes(${this.reviewVotes})`) // Text显示10Button(`reviewVotes(${this.reviewVotes}), give +1`).onClick(() => this.reviewVotes += 1)}.width('50%')}
}@Component
struct Child {@Provide({ allowOverride: "reviewVotes" }) reviewVotes: number = 10;build() {Row({ space: 5 }) {GrandSon()}}
}@Component
struct Parent {@Provide({ allowOverride: "reviewVotes" }) reviewVotes: number = 20;build() {Child()}
}@Entry
@Component
struct GrandParent {@Provide("reviewVotes") reviewVotes: number = 40;build() {Column() {Button(`reviewVotes(${this.reviewVotes}), give +1`).onClick(() => this.reviewVotes += 1)Parent()}}
}

在上面的示例中:

  • GrandParent声明了@Provide(“reviewVotes”) reviewVotes: number = 40
  • Parent是GrandParent的子组件,声明@Provide为allowOverride,重写父组件GrandParent中的reviewVotes变量为20。如果不设置allowOverride,则会抛出运行时报错,提示@Provide重复定义。Child同理。
  • GrandSon在初始化@Consume的时候,@Consume装饰的变量通过相同的属性名绑定其最近的祖先的@Provide装饰的变量
  • GrandSon查找到相同属性名的@Provide在祖先Child中,所以@Consume(“reviewVotes”) reviewVotes: number初始化数值为10。如果Child中没有定义与@Consume同名的@Provide,则继续向上寻找Parent中的同名@Provide值为20,以此类推。
  • 如果查找到根节点还没有找到key对应的@Provide,则会报初始化@Consume找不到@Provide的报错。

@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

前边我们讲到的装饰器,对于class的观测,都无法观测到嵌套属性但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。

概述

@ObjectLink和@Observed类装饰器用于涉及嵌套对象或数组的场景中进行双向数据同步:

  • 被@Observed装饰的类,可以被观察到属性的变化。
  • 子组件中@ObjectLink装饰器装饰的状态变量,用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。
  • @Observed用于嵌套类场景中,观察对象类属性变化,要配合自定义组件使用(示例详见嵌套对象),如果要做数据双/单向同步,需要搭配@ObjectLink或者@Prop使用。

限制条件

  • 使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
  • @ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
  • @ObjectLink装饰的数据为可读类型,不允许@ObjectLink装饰的数据自身赋值。
  • 如果需要使用赋值操作,使用@Prop。

观察变化

  • @Observed装饰的类,如果其属性为非简单类型,比如class、Object或者数组,也需要被@Observed装饰,否则将观察不到其属性的变化。

  • @ObjectLink只能接收被@Observed装饰的class的实例。

  • 继承Date的class时,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds 更新Date的属性。

  • 继承Map的class时,可以观察到Map整体的赋值,同时可通过调用Map的接口set, clear, delete 更新Map的值。

  • 继承Set的class时,可以观察到Set整体的赋值,同时可通过调用Set的接口add, clear, delete 更新Set的值。

框架行为

  1. 初始渲染
    • @Observed装饰的class的实例会被不透明的代理对象包装,代理了class上的属性的setter和getter方法
    • 子组件中@ObjectLink装饰的从父组件初始化,接收被@Observed装饰的class的实例,@ObjectLink的包装类会将自己注册给@Observed class。
  2. 属性更新:
    • 当@Observed装饰的class属性改变时,会走到代理的setter和getter,然后遍历依赖它的@ObjectLink包装类,通知其数据更新。

这篇关于ArkUI-状态管理-@Provide、@Consume、@Observed、@ObjectLink的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1133564

相关文章

nvm如何切换与管理node版本

《nvm如何切换与管理node版本》:本文主要介绍nvm如何切换与管理node版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录nvm切换与管理node版本nvm安装nvm常用命令总结nvm切换与管理node版本nvm适用于多项目同时开发,然后项目适配no

Redis实现RBAC权限管理

《Redis实现RBAC权限管理》本文主要介绍了Redis实现RBAC权限管理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1. 什么是 RBAC?2. 为什么使用 Redis 实现 RBAC?3. 设计 RBAC 数据结构

Flutter监听当前页面可见与隐藏状态的代码详解

《Flutter监听当前页面可见与隐藏状态的代码详解》文章介绍了如何在Flutter中使用路由观察者来监听应用进入前台或后台状态以及页面的显示和隐藏,并通过代码示例讲解的非常详细,需要的朋友可以参考下... flutter 可以监听 app 进入前台还是后台状态,也可以监听当http://www.cppcn

mac安装nvm(node.js)多版本管理实践步骤

《mac安装nvm(node.js)多版本管理实践步骤》:本文主要介绍mac安装nvm(node.js)多版本管理的相关资料,NVM是一个用于管理多个Node.js版本的命令行工具,它允许开发者在... 目录NVM功能简介MAC安装实践一、下载nvm二、安装nvm三、安装node.js总结NVM功能简介N

MySQL 中的服务器配置和状态详解(MySQL Server Configuration and Status)

《MySQL中的服务器配置和状态详解(MySQLServerConfigurationandStatus)》MySQL服务器配置和状态设置包括服务器选项、系统变量和状态变量三个方面,可以通过... 目录mysql 之服务器配置和状态1 MySQL 架构和性能优化1.1 服务器配置和状态1.1.1 服务器选项

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的