OpenHarmony后代组件双向同步,跨层级传递:@Provide装饰器和@Consume装饰器
其中@Provide装饰的变量是在祖先节点中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费(绑定)”祖先节点提供的变量。
说明:
从API version 9开始,这两个装饰器支持在ArkTS卡片中使用。
概述
@Provide/@Consume装饰的状态变量有以下特性:
● @Provide装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide的方便之处在于,开发者不需要多次在组件之间传递变量。
● 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。
● @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装饰的变量,会发生运行时报错。
装饰器说明
@State的规则同样适用于@Provide,差异为@Provide还作为多层后代的同步源。
|
@Provide变量装饰器 |
说明 |
|
装饰器参数 |
别名:常量字符串,可选。 如果指定了别名,则通过别名来绑定变量;如果未指定别名,则通过变量名绑定变量。 |
|
同步类型 |
双向同步。 从@Provide变量到所有@Consume变量以及相反的方向的数据同步。双向同步的操作与@State和@Link的组合相同。 |
|
允许装饰的变量类型 |
Object、class、string、number、boolean、enum类型,以及这些类型的数组。 支持Date类型。 支持类型的场景请参考观察变化。 不支持any,不支持简单类型和复杂类型的联合类型,不允许使用undefined和null。 必须指定类型。@Provide变量的@Consume变量的类型必须相同。 说明: 不支持Length、ResourceStr、ResourceColor类型,Length、ResourceStr、ResourceColor为简单类型和复杂类型的联合类型。 |
|
被装饰变量的初始值 |
必须指定。 |
|
@Consume变量装饰器 |
说明 |
|
装饰器参数 |
别名:常量字符串,可选。 如果提供了别名,则必须有@Provide的变量和其有相同的别名才可以匹配成功;否则,则需要变量名相同才能匹配成功。 |
|
同步类型 |
双向:从@Provide变量(具体请参见@Provide)到所有@Consume变量,以及相反的方向。双向同步操作与@State和@Link的组合相同。 |
|
允许装饰的变量类型 |
Object、class、string、number、boolean、enum类型,以及这些类型的数组。 支持Date类型。 支持类型的场景请参考观察变化。 不支持any,不允许使用undefined和null。 必须指定类型。@Provide变量的@Consume变量的类型必须相同。 说明: @Consume装饰的变量,在其父节点或者祖先节点上,必须有对应的属性和别名的@Provide装饰的变量。 |
|
被装饰变量的初始值 |
无,禁止本地初始化。 |
变量的传递/访问规则说明
|
@Provide传递/访问 |
说明 |
|
从父组件初始化和更新 |
可选,允许父组件中常规变量(常规变量对@Prop赋值,只是数值的初始化,常规变量的变化不会触发UI刷新,只有状态变量才能触发UI刷新)、@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的时候,可以观察到数组的添加、删除、更新数组单元。
● 当装饰的对象是Date时,可以观察到Date整体的赋值,同时可通过调用Date的接口setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds 更新Date的属性。
@Component
struct CompD { @Consume selectedDate: Date; build() {
Column() {
Button(`child increase the day by 1`)
.onClick(() => {
this.selectedDate.setDate(this.selectedDate.getDate() + 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 CompA { @Provide selectedDate: Date = new Date('2021-08-08') build() {
Column() {
Button('parent increase the day by 1')
.margin(10)
.onClick(() => {
this.selectedDate.setDate(this.selectedDate.getDate() + 1)
})
Button('parent update the new date')
.margin(10)
.onClick(() => {
this.selectedDate = new Date('2023-07-07')
})
DatePicker({
start: new Date('1970-1-1'),
end: new Date('2100-1-1'),
selected: this.selectedDate
})
CompD()
}
}
}
框架行为
1. 初始渲染:
a. @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件;
b. 子组件中如果使用@Consume变量,则会在map中查找是否有该变量名/alias(别名)对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR;
c. 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会保存在map中查找到的@Provide变量,并把自己注册给@Provide。
2. 当@Provide装饰的数据变化时:
a. 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
b. 通知@Consume更新后,子组件所有依赖@Consume的系统组件(elementId)都会被通知更新。以此实现@Provide对@Consume状态数据同步。
3. 当@Consume装饰的数据变化时:
通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新的数值同步回@Provide,以此实现@Consume向@Provide的同步更新。
使用场景
在下面的示例是与后代组件双向同步状态@Provide和@Consume场景。当分别点击CompA和CompD组件内Button时,reviewVotes 的更改会双向同步在CompA和CompD中。
@Component
struct CompD {
// @Consume装饰的变量通过相同的属性名绑定其祖先组件CompA内的@Provide装饰的变量
@Consume reviewVotes: number; build() {
Column() {
Text(`reviewVotes(${this.reviewVotes})`)
Button(`reviewVotes(${this.reviewVotes}), give +1`)
.onClick(() => this.reviewVotes += 1)
}
.width('50%')
}
} @Component
struct CompC {
build() {
Row({ space: 5 }) {
CompD()
CompD()
}
}
} @Component
struct CompB {
build() {
CompC()
}
} @Entry
@Component
struct CompA {
// @Provide装饰的变量reviewVotes由入口组件CompA提供其后代组件
@Provide reviewVotes: number = 0; build() {
Column() {
Button(`reviewVotes(${this.reviewVotes}), give +1`)
.onClick(() => this.reviewVotes += 1)
CompB()
}
}
}
OpenHarmony后代组件双向同步,跨层级传递:@Provide装饰器和@Consume装饰器的更多相关文章
- 禧云Redis跨机房双向同步实践
编者荐语: 2019年4月16日跨机房Redis同步中间件(Rotter)上线,团餐率先商用: 以下文章来源于云纵达摩院 ,作者杨海波 禧云信息/研发中心/杨海波 20191115 关键词:Rot ...
- $attrs/inheritAttrs可以实现组件的跨级传递
$attrs/inheritAttrs可以实现组件的跨级传递 // 问题1 为什么this.$attrs可以得到主 传递过来的值 //$attrs 说明 // ...
- Vue组件跨层级通信
正常组件间通信 父->子组件 是通过属性传递 子->父组件 是通过this.$emit()传递 this.$emit()返回的是this,如果需要一些值 可使用callback方式传递 p ...
- Vue使用Ref跨层级获取组件实例
目录 Vue使用Ref跨层级获取组件实例 示例介绍 文档目录结构 安装vue-ref 根组件自定义方法[使用provide和inject] 分别说明各个页面 结果 Vue使用Ref跨层级获取组件实例 ...
- 原生Redis跨数据中心双向同步优化实践
一.背景 公司基于业务发展以及战略部署,需要实现在多个数据中心单元化部署,一方面可以实现多数据中心容灾,另外可以提升用户请求访问速度.需要保证多数据中心容灾或者实现用户就近访问的话,需要各个数据中心拥 ...
- vue父子组件状态同步的最佳方式
哈喽!大家好!我是木瓜太香,一位老牌儿前端工程师,平时我们在使用 vue 开发的时候,可能会遇到需要父组件与子组件某个状态需要同步的情况,通常这个是因为我们封装组件的时候有一个相同的状态外面要用,里面 ...
- vue父子组件状态同步的最佳方式续章(v-model篇)
大家好!我是木瓜太香!一名前端工程师,之前写过一篇<vue父子组件状态同步的最佳方式>,这篇文章描述了大多数情况下的父子组件同步的最佳方式,也是被开源中国官方推荐了,在这里表示感谢! 这次 ...
- 配置ogg异构oracle-mysql 双向同步注意事项
双向同步需要考虑的是怎么解决循环复制,以及同时更新一张表以谁为基准. 配置过程就不写了,大致和oracle到mysql的单向+mysql到oracle的单向差不多. 需要注意的有如下几点: 1.ora ...
- vue 祖先组件操作后代组件方法
前言:最近写代码遇到一问题:祖先级别的组件怎么操作孙子的儿子的组件方法(是不是已经绕晕了),在网上搜了半天都是父子传参,父子操作,晕晕乎乎的想起了bus(事件总线), 原理就是:是在vue原型上挂载( ...
- MySQL 数据库双向同步复制
MySQL 复制问题的最后一篇,关于双向同步复制架构设计的一些设计要点与制约. 问题和制约 数据库的双主双写并双向同步场景,主要考虑数据完整性.一致性和避免冲突.对于同一个库,同一张表,同一个记录中的 ...
随机推荐
- python字符串模板文本处理之Template
from string import Template s = Template('$who 在 $do') ts = s.substitute(who="张三", do=&quo ...
- 【Azure API 管理】在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端,在请求中携带Token访问后报401的错误
问题描述 在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端的文档中操作 "在开发人员门户中启用 OAuth 2.0 用户授权&qu ...
- Nebula Graph 在众安保险的图实践
本文首发于 Nebula Graph Community 公众号 互联网金融的借贷同传统信贷业务有所区别,相较于传统信贷业务,互联网金融具有响应快.数据规模大.风险高等特点.众安保险主要业务是做信用保 ...
- C#的托盘窗体显示与隐藏效果 - 开源研究系列文章
今天无聊,进行的C#的编码内容仍然在继续.这些天不断地在完善及编写C#的Winform相关的代码,并将其整理形成博文.这次带来的是关于窗体的显示及隐藏效果的代码段.上次有过一个代码,这次当做新代码进行 ...
- 测绘线性代数(四):数学期望、协方差、PCA
数学期望 E(X) = ∑pixi,X为所有xi的集合,pi为xi对应的概率. 通常来说,xi都是离散的,除非像高斯分布,假设xi不是离散的,才用上式. 当xi是离散的,那么: E(X) = 1 / ...
- Java 异常处理(1) :try-catch-finally的使用
1 package com.bytezero.throwable; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 impor ...
- C++ //类模板对象做函数参数 //三种方式 //1.指定传入的类型 --直接显示对象的数据类型 //2.参数模板化 --将对象中的参数变为模板进行传递 //3.整个类模板化 --将这个对象类型 模板化进行传递
1 //类模板对象做函数参数 2 //三种方式 3 //1.指定传入的类型 --直接显示对象的数据类型 4 //2.参数模板化 --将对象中的参数变为模板进行传递 5 //3.整个类模板化 --将这个 ...
- 适合新手练习的python开源经典源码
一 前记 python学习离不开三要素: A.基础知识要熟悉 B. 练习源码要够量 C.实战项目要跟上 二 链接 书本的基础就看几本书就可以了,这里给出源码练习的经典开源源码: 该链接集合了pytho ...
- day01-数据库的安装和使用
Java数据库的安装和使用 1.数据库的作用 一个问题:淘宝网.京东.微信抖音,都有各自的功能,那么我们退出系统的时候,为什么信息还在? 解决之道-文件,数据库 为了解决上诉问题,使用更加利于管理数据 ...
- Welcome to YARP - 1.认识 YARP 并构建反向代理服务
目录 Welcome to YARP - 1.认识YARP并搭建反向代理服务 Welcome to YARP - 2.配置功能 Welcome to YARP - 3.负载均衡 Welcome to ...