写点什么

鸿蒙 5.0 应用开发——V2 装饰器 @Provider 和 @Consumer 的使用

作者:高心星
  • 2025-09-17
    江苏
  • 本文字数:2455 字

    阅读完需:约 8 分钟

鸿蒙5.0应用开发——V2装饰器@Provider和@Consumer的使用

【高心星出品】

V2 装饰器 @Provider 和 @Consumer 的使用

概念

@Provider 和 @Consumer 用于跨组件层级数据双向同步,可以使得开发者不用拘泥于组件层级。


@Provider 和 @Consumer 属于状态管理 V2 装饰器,所以只能在 @ComponentV2 中才能使用,在 @Component 中使用会编译报错。


@Provider 和 @Consumer 提供了跨组件层级数据双向同步的能力。

概述

@Provider,即数据提供方,其所有的子组件都可以通过 @Consumer 绑定相同的 key 来获取 @Provider 提供的数据。


@Consumer,即数据消费方,可以通过绑定同样的 key 获取其最近父节点的 @Provider 的数据,当查找不到 @Provider 的数据时,使用本地默认值。图示如下。



@Provider 和 @Consumer 装饰的数据类型需要一致。


开发者在使用 @Provider 和 @Consumer 时要注意:


  • @Provider 和 @Consumer 强依赖自定义组件层级,@Consumer 会因为所在组件的父组件不同,而被初始化为不同的值。

  • @Provider 和 @Consumer 相当于把组件粘合在一起了,从组件独立角度考虑,应减少使用 @Provider 和 @Consumer。

一、核心机制
  1. 双向同步原理

  2. @Provider:作为数据提供方,在父组件中声明共享状态,允许所有子组件通过相同 key 访问。

  3. @Consumer:作为数据消费方,在后代组件中绑定 @Provider 的同名 key,自动同步数据变化。

  4. 双向绑定:@Provider 的属性更新会触发 @Consumer 的同步,反之 @Consumer 的修改也会反向更新 @Provider。

  5. 依赖关系

  6. 必须与**@ComponentV2**组件配合使用,在传统 @Component 中会报错。

  7. 数据类型必须一致,且通过 alias(别名)或属性名唯一匹配。若未指定 alias,默认以属性名为匹配依据。


二、与 V1 版本(@Provide/@Consume)的对比



三、关键限制与注意事项
  1. 初始化规则

  2. @Provider 必须本地初始化,禁止从父组件传参初始化

  3. @Consumer 可设置默认值(如@Consumer() count: number = 100),避免因找不到 @Provider 导致崩溃。

  4. 兼容性限制

  5. 禁止与 V1 装饰器(@Provide、@Consume)混用。

  6. 若需观测嵌套对象属性变化,必须为嵌套类添加 @ObservedV2 和 @Trace 装饰器。

  7. 使用场景优化

  8. 适用场景:跨多层级组件传递状态(如全局主题、用户配置)。

  9. 避免滥用:过度使用会增加组件间耦合,优先考虑父子组件直接传参。

案例

祖孙数据同步:


下面案例 page 加载 parent 组件,parent 组件加载 child 组件,page 定义的 count 由 @provider 装饰,child 定义的 count 由 @consumer 装饰,两者建立双向同步关系。



@ComponentV2struct parent{  build() {    cchild()  }}
@ComponentV2struct cchild{ // 名字一致的情况,可以不用加别名 @Consumer() count:number=11 // 如果名字不一致就用别名 // @Consumer('count') cc:number=11 build() { Column(){ Button('child count: '+this.count) .width('60%') .onClick(()=>{ this.count++ }) } .width('100%') .padding(20) }}


@Entry@ComponentV2struct Providerpage { // 数据提供 别名为count @Provider() count:number=10 build() { Column({space:20}){ Button('page count: '+this.count) .width('60%') .onClick(()=>{ this.count++ }) parent() } .height('100%') .width('100%') }}
复制代码


祖孙数据同步的同时配合 param 的单向同步:


在上面案例的基础上,在 parent 中加入了 count 由 @param 装饰,在页面中通过单向同步绑定,从某种角度看,@provider 和 @consumer 都有 @local 的部分功能。



@ComponentV2struct parent{  // 此处为count param的数据 本地无法更新,需要父组件更新  @Require @Param count:number  build() {    Column() {      cchild1()      Button('parent count:'+this.count)        .width('60%')    }.width('100%')    .padding(20)    .backgroundColor(Color.Gray)  }}@ComponentV2struct cchild1{  // 名字一致的情况,可以不用加别名  @Consumer() count:number=11  // 如果名字不一致就用别名  // @Consumer('count') cc:number=11  build() {    Column(){      Button('child count: '+this.count)        .width('60%')        .onClick(()=>{          this.count++        })    }    .width('100%')    .padding(20)  }}@Entry@ComponentV2struct Providerpage1 {  // 数据提供 别名为count  @Provider() count:number=10  build() {    Column({space:20}){      Button('page count: '+this.count)        .width('60%')        .onClick(()=>{          this.count++        })      // page与parent组件建立单向绑定      parent({count:this.count})    }    .height('100%')    .width('100%')  }}
复制代码


复杂数据的双向同步问题:


在上面案例的基础上,将 count 这种基础类型转化成类 temp,形成复杂数据类型,如果想要双向同步就必须要给类加上 @observedV2 和 @Trace 装饰器,才能观察到属性的变化。



@ObservedV2class temp{  @Trace count:number
constructor(count: number) { this.count = count }
}
@ComponentV2struct parent2{ build() { cchild2() }}
@ComponentV2struct cchild2{ // 名字一致的情况,可以不用加别名 @Consumer() t:temp=new temp(11) // 如果名字不一致就用别名 // @Consumer('count') cc:number=11 build() { Column(){ Button('child count: '+this.t.count) .width('60%') .onClick(()=>{ this.t.count+=1 // this.t=new temp(this.t.count+1) }) } .width('100%') .padding(20) }}
@Entry@ComponentV2struct Providerpage2 { // 数据提供 别名为count @Provider() t:temp=new temp(10) build() { Column({space:20}){ Button('page count: '+this.t.count) .width('60%') .onClick(()=>{ this.t.count+=1 }) parent2() } .height('100%') .width('100%') }}
复制代码


发布于: 刚刚阅读数: 6
用户头像

高心星

关注

天将降大任于斯人也,必先苦其心志。 2024-10-17 加入

华为开发者专家(HDE)。 10年教学经验,兼任多家科技公司技术顾问。先后从事JavaEE项目开发、Python爬虫、HarmonyOS移动应用开发等课程的教学工作。参与开发《鸿蒙应用开发基础》和《鸿蒙项目实战》等课程。

评论

发布
暂无评论
鸿蒙5.0应用开发——V2装饰器@Provider和@Consumer的使用_鸿蒙_高心星_InfoQ写作社区