当前位置: 首页 > news >正文

鸿蒙进阶篇-状态管理之@Provide与@Consume

大家好,这里是鸿蒙开天组,今天我们来学习一下状态管理中的@Provide与@Consume。

一、概述

嘿!大家还记得这张图吗?不记得也要记得哦,因为这张图里的东西,既是高频必考面试题,也是实际开发中,经常需要用到的玩意,大致上可以这么理解:

下面Components框起来的部分,就是组件之间的状态变量的管理,也就是数据通讯,它会涉及到组件之间的关系,比如父子关系,比如祖孙关系或者其他跨级关系等等。

昨天我们已经学习了左下角的@Prop和@Link,今天需要学的就在中间位置:

 @Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量。

二、基础使用

先附上官方文档链接:@Provide装饰器和@Consume装饰器

官方文档写的东西比较多,对于新手来说不太容易理解消化和抓住重点,所以我们这里提供了基础结构:

// 写法 1:通过相同的变量名绑定
@Provide a: number = 0;
@Consume a: number;// 写法 2通过相同的变量别名绑定
@Provide b: number = 0;
@Consume('b') c: number;

简单来说,使用步骤就是:

  1. 将爷组件的状态属性使用@Provide修饰
  2. 孙组件通过@Consume修饰

 三、例子说明

这里按步骤一步步来,先给出基础代码模板,大家理解一下其中的结构:

@Entry
@Component// 爷级组件
struct GrandfatherComponent {build() {Column() {Text('爷级组件').fontSize(30).fontWeight(900)ParentComponent()}.padding(10).height('100%').backgroundColor(Color.Gray).width('100%').alignItems(HorizontalAlign.Center).padding({ top: 100 })}
}@Component// 父级组件
struct ParentComponent {// 编写 UIbuild() {Column({ space: 20 }) {Text('我是父级组件').fontSize(22).fontWeight(900)GrandsonComponent()}.backgroundColor(Color.Pink).alignItems(HorizontalAlign.Center).width('90%').margin({ top: 50 }).padding(10).borderRadius(10)}
}@Component// 孙级组件
struct GrandsonComponent {// 编写 UIbuild() {Column({ space: 20 }) {Text('我是孙级组件').fontSize(20).fontWeight(900)}.backgroundColor(Color.Orange).alignItems(HorizontalAlign.Center).width('90%').margin({ top: 50 }).padding(10).borderRadius(10)}
}

界面显示如下:

现在的需求是爷级组件和孙级组件通信传值,问题是,从代码结构上看,中间还隔了一个父级组件。虽然我们也可以基于上一篇讲的@State+@Prop,从爷->父->孙这样实现,但是管理起来毕竟有一个中间商不那么方便,而且这也是华为官方不推荐的做法,因为会消耗额外的性能。所以,我们采用了@Provide+@Consume的方式来实现:

interface Cat {name: stringage: number
}@Entry
@Component// 爷级组件
struct GrandfatherComponent {@Provide cat: Cat = { name: '小花', age: 3 }@Provide food: string = 'fish'build() {Column() {Text('爷级组件').fontSize(30).fontWeight(900)ParentComponent()}.padding(10).height('100%').backgroundColor(Color.Gray).width('100%').alignItems(HorizontalAlign.Center).padding({ top: 100 })}
}@Component// 父级组件
struct ParentComponent {// 编写 UIbuild() {Column({ space: 20 }) {Text('我是父级组件').fontSize(22).fontWeight(900)GrandsonComponent()}.backgroundColor(Color.Pink).alignItems(HorizontalAlign.Center).width('90%').margin({ top: 50 }).padding(10).borderRadius(10)}
}@Component// 孙级组件
struct GrandsonComponent {// 相同变量名@Consume cat: Cat@Consume('food') f: string// 编写 UIbuild() {Column({ space: 20 }) {Text('我是孙级组件').fontSize(20).fontWeight(900)Text(JSON.stringify(this.cat))Text(this.f)Button('修改').onClick(() => {this.cat.name = '小美'this.cat.age = 99this.f += '!'})}.backgroundColor(Color.Orange).alignItems(HorizontalAlign.Center).width('90%').margin({ top: 50 }).padding(10).borderRadius(10)}
}

点击修改效果如下:

 四、补充

1.@Provide+@Consume也是开发中很常用的一对,尤其是组件跨级关系复杂的时候,这个时候就只需要定义一个@Provide在祖级组件中定义,其他多个后代组件@Consume接收即可;

2.在build方法内,当@Provide与@Consume装饰的变量是Object类型、且通过a.b(this.object)形式调用时,b方法内传入的是this.object的原生对象,修改其属性,无法触发UI刷新,尝试思考下以下例子该如何修改,才能触发UI刷新吧(参考答案在官方文档的最后):

class Animal {name:string;type:string;age: number;constructor(name:string, type:string, age:number) {this.name = name;this.type = type;this.age = age;}static changeName1(animal:Animal) {animal.name = 'Black';}static changeAge1(animal:Animal) {animal.age += 1;}
}@Entry
@Component
struct Demo1 {@Provide dog:Animal = new Animal('WangCai', 'dog', 2);changeAge2(animal:Animal) {animal.age += 2;}build() {Column({ space:10 }) {Text(`Demo1: This is a ${this.dog.age}-year-old ${this.dog.type} named ${this.dog.name}.`).fontColor(Color.Red).fontSize(30)Button('changeAge1').onClick(()=>{// 通过静态方法调用,无法触发UI刷新Animal.changeAge1(this.dog);})Button('changeAge2').onClick(()=>{// 使用this通过自定义组件内部方法调用,无法触发UI刷新this.changeAge2(this.dog);})Demo2()}}
}@Component
struct Demo2 {build() {Column({ space:10 }) {Text(`Demo2.`).fontColor(Color.Blue).fontSize(30)Demo3()}}
}@Component
struct Demo3 {@Consume dog:Animal;changeName2(animal:Animal) {animal.name = 'White';}build() {Column({ space:10 }) {Text(`Demo3: This is a ${this.dog.age}-year-old ${this.dog.type} named ${this.dog.name}.`).fontColor(Color.Yellow).fontSize(30)Button('changeName1').onClick(()=>{// 通过静态方法调用,无法触发UI刷新Animal.changeName1(this.dog);})Button('changeName2').onClick(()=>{// 使用this通过自定义组件内部方法调用,无法触发UI刷新this.changeName2(this.dog);})}}
}

好啦,今天的分享就到这里,感谢阅读,你的点赞和收藏都是莫大的支持!

相关文章:

鸿蒙进阶篇-状态管理之@Provide与@Consume

大家好,这里是鸿蒙开天组,今天我们来学习一下状态管理中的Provide与Consume。 一、概述 嘿!大家还记得这张图吗?不记得也要记得哦,因为这张图里的东西,既是高频必考面试题,也是实际开发中&…...

java集合及源码

目录 一.集合框架概述 1.1集合和数组 数组 集合 1.2Java集合框架体系 常用 二. Collection中的常用方法 添加 判断 删除 其它 集合与数组的相互转换 三Iterator(迭代器)接口 3.0源码 3.1作用及格式 3.2原理 3.3注意 3.4获取迭代器(Iterator)对象 3.5. 实现…...

GraphRAG访问模式和知识图谱建模

GraphRAG访问模式和知识图谱建模 GraphRAG访问模式和知识图谱建模什么是GraphRAG了解文本分块检索模式图谱建模相关概念图结构 GraphRAG访问模式和知识图谱建模 graphrag.com是一个开源项目,收集了围绕GraphRAG的相关资源,目前正在快速收集大家的投稿。深…...

TCP/IP协议攻击与防范

一、TCP/IP协议攻击介绍 1.1 Internet的结构​ LAN:局域网 WAN:广域网 WLAN:无线局域网 私有IP地址与公有IP地址? 私有地址:A类:10.0.0.0~10.255.255.255 B类:172.16.0.0~172.31.255.255…...

Java基于 SpringBoot+Vue的口腔管理平台(附源码+lw+部署)

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

11.26深度学习_神经网络-数据处理

一、深度学习概述 1. 什么是深度学习 ​ 人工智能、机器学习和深度学习之间的关系: ​ 机器学习是实现人工智能的一种途径,深度学习是机器学习的子集,区别如下: ​ 传统机器学习算法依赖人工设计特征、提取特征,而深…...

【人工智能】Python常用库-TensorFlow常用方法教程

TensorFlow 是一个广泛应用的开源深度学习框架,支持多种机器学习任务,如深度学习、神经网络、强化学习等。以下是 TensorFlow 的详细教程,涵盖基础使用方法和示例代码。 1. 安装与导入 安装 TensorFlow: pip install tensorflow…...

微信小程序按字母顺序渲染城市 功能实现详细讲解

在微信小程序功能搭建中,按字母渲染城市会用到多个ES6的方法,如reduce,map,Object.entries(),Object.keys() ,需要组合熟练掌握,才能优雅的处理数据完成渲染。 目录 一、数据分析 二、数据处理 …...

23省赛区块链应用与维护(房屋租凭【下】)

23省赛区块链应用与维护(房屋租凭) 背景描述 随着异地务工人员的增多,房屋租赁成为一个广阔市场。目前,现有技术中的房屋租赁是由房主发布租赁信息,租赁信息发布在房屋中介或租赁软件,租客获取租赁信息后,现场看房,并签订纸质的房屋租赁合同,房屋租赁费用通过中介或…...

数据结构-图-领接表存储

一、了解图的领接表存储 1、定义与结构 定义:邻接表是图的一种链式存储结构,它通过链表将每个顶点与其相邻的顶点连接起来。 结构: 顶点表:通常使用一个数组来存储图的顶点信息,数组的每个元素对应一个顶点&#xff…...

快速入门web安全

一.确定初衷 1.我真的喜欢搞安全吗? 2.我只是想通过安全赚钱钱吗? 3.我不知道做什么就是随便。 4.一辈子做信息安全吗 这些不想清楚会对你以后的发展很不利,与其盲目的学习web安全,不如先做一个长远的计划。 否则在我看来都是浪费时间。如果你考虑好了…...

rabbitMq两种消费应答失败处理方式

在rabbitMq消费端,有三种应答模式: none:不处理。即消息投递给消费者后立刻 ack 消息会立刻从MQ删除。非常不安全,不建议使用 manual:手动模式。需要自己在业务代码中调用api,发送 ack 或 reject&#xff…...

Qt C++(一) 5.12安装+运行第一个项目

安装 1. Download Qt OSS: Get Qt Online Installer 在该链接中下载qt在线安装程序 2. 安装时候,注意关键一步,archive是存档的意思,可以找到旧的版本, 比如5.12 3. 注意组件没必要全选,否则需要安装50个g, 经过请教…...

【RISC-V CPU Debug 专栏 1 -- RISC-V debug 规范】

文章目录 RISC-V Debug调试用例支持的功能限制和不包括的内容RISC-V 调试架构的主要组件用户与调试主机调试翻译器调试传输硬件调试传输模块(DTM)调试模块(DM)调试功能触发模块版本介绍RISC-V Debug RISC-V 调试规范为 RISC-V 处理器提供了一套标准化的调试接口和功能,旨…...

使用Gradle编译前端的项目

使用Gradle编译前端的项目 前言项目结构根项目(parent-project)的 settings.gradle.kts后端项目(backend)的 build.gradle.kts前端项目(frontend)的 build.gradle.kts打包bootJar 前言 最近的项目都是使用…...

网络爬虫——常见问题与调试技巧

在开发网络爬虫的过程中,开发者常常会遇到各种问题,例如网页加载失败、数据提取错误、反爬机制限制等。以下内容将结合实际经验和技术方案,详细介绍解决常见错误的方法,以及如何高效调试和优化爬虫代码。 1. 爬虫过程中常见的错误…...

【AI绘画】Midjourney进阶:色调详解(下)

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AI绘画 | Midjourney 文章目录 💯前言💯Midjourney中的色彩控制为什么要控制色彩?为什么要在Midjourney中控制色彩? 💯色调纯色调灰色调暗色调 &#x1f4af…...

springboot+redis+lua实现分布式锁

1 分布式锁 Java锁能保证一个JVM进程里多个线程交替使用资源。而分布式锁保证多个JVM进程有序交替使用资源,保证数据的完整性和一致性。 分布式锁要求 互斥。一个资源在某个时刻只能被一个线程访问。避免死锁。避免某个线程异常情况不释放资源,造成死锁…...

【Petri网导论学习笔记】Petri网导论入门学习(十一) —— 3.3 变迁发生序列与Petri网语言

目录 3.3 变迁发生序列与Petri网语言定义 3.4定义 3.5定义 3.6定理 3.5例 3.9定义 3.7例 3.10定理 3.6定理 3.7 有界Petri网泵引理推论 3.5定义 3.9定理 3.8定义 3.10定义 3.11定义 3.12定理 3.93.3 变迁发生序列与Petri网语言 对于 Petri 网进行分析的另一种方法是考察网系统…...

docker-compose文件的简介及使用

Docker Compose是Docker官方的开源项目,主要用于定义和运行多容器Docker应用。以下是对Docker Compose的详细介绍: 一、主要功能: 容器编排:Docker Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML格…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如&#xff1a…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

Kafka入门-生产者

生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...

MySQL 主从同步异常处理

阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示&#xff…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...