前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >鸿蒙next开发中父子组件如何进行数据通信(状态管理v1版)?

鸿蒙next开发中父子组件如何进行数据通信(状态管理v1版)?

原创
作者头像
言程序
发布2024-12-27 09:22:41
发布2024-12-27 09:22:41
1310
举报
文章被收录于专栏:鸿蒙鸿蒙

鸿蒙next开发中父子组件如何进行数据通信(状态管理v1版)?

【问题描述】:我们经常在开发的时候,需要在父子组件进行数据的传递,有哪几种常见的用法?

【解决方案】:以下几种解决方案可以满足70%的应用场景。

一、@state 和 @prop
  1. @State:装饰的变量值修改时,页面也会随之更新
  2. @Prop: 配合@State使用,实现页面单向传递 数据从父组件传入子组件,父组件数据修改,子组件UI更新;在子组件中修改,父组件ui不更新 (传递值时使用this.)

代码示例

父组件

代码语言:js
复制
import  Child from '../view/Child'//引入子组件
@Entry
@Component
struct Index {
  @State showNumber2:number=0
  build() {
    Column() {
      Row() {
        Text('showNumber2:'+this.showNumber2)
          .fontSize(40)
      }
      .width('100%')
      Row() {
      Button('加1').width('100%').height(50).onClick(()=>{
        this.showNumber2++
      })
      }
      .width('100%')
      //子组件
      Row(){
        Child({
          showNumber2:this.showNumber2,
          //由于@Prop装饰器是单向传递 所以可以使用回调函数的方式来修改父组件的值
          giveIndex:(data)=>{
            if(data){
              this.showNumber2=parseInt(data)
            }else {
              this.showNumber2=0
            }
        }})
      }.width('100%')
    }
    .height('100%')
    .width('100%')

  }
}

子组件

代码语言:js
复制
@Component
export default struct Child {
  @Prop showNumber2:number
  // 回调函数
  giveIndex=(data)=>{
  }
  build() {
    Column() {
      Row() {
        Text('@Prop装饰器:')
        TextInput({text:JSON.stringify(this.showNumber2)})
          .width('100%')
          .type(InputType.Number)
          .height(50)
          .onChange((value)=>{
            //使用回调可以修改父组件的值
            //this.giveIndex(value)
            //传入修改无效
            if(value){
              this.showNumber2=parseInt(value)
            }else  {
              this.showNumber2=0
            }
          })
      }
      .width('50%')
    }
  }
}
二、@state 和 @Link:

配合@State使用,子组件用@Link接收, 可以实现页面双向传递 数据从父组件传入子组件,在子组件中修改则父组件ui更新 (传递值时使用$)

父组件

代码语言:js
复制
import  Child from '../view/Child'//引入子组件
@Entry
@Component
struct Index {
  @State showNumber1:number=0
  build() {
    Column() {
      Row() {
        Text('showNumber1:'+this.showNumber1)
          .fontSize(40)
      }
      .width('100%')
      Row() {
      Button('加1').width('100%').height(50).onClick(()=>{
        this.showNumber1= this.showNumber1+1
      })
      }
      .width('100%')
      Row(){
        Child({showNumber1:$showNumber1}) //注意这里传参是用的$
      }.width('100%')
    }
    .height('100%')
    .width('100%')

  }
}

子组件

代码语言:js
复制
@Component
export default struct Child {
  @Link showNumber1:number
  build() {
    Column() {
      Row() {
        Text('@Link装饰器:')
        TextInput({text:JSON.stringify(this.showNumber1)})
          .width('100%')
          .type(InputType.Number)
          .height(50)
          .onChange((value)=>{
            if(value){
              this.showNumber1=parseInt(value)
            }else  {
              this.showNumber1=0
            }
          })
      }
      .width('50%')
    }
  }
}
三 、@Provide 和 @Consume

1、@Provide/@Consume 配套使用,可以跨组件传值并且双向同步,在调用组件时不需要传递参数,能直接获取,ui更新 (不需要再组件调用中传值)

2、不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递

父组件:

代码语言:js
复制
import  Child from '../view/Child'//引入子组件
@Entry
@Component
struct Index {
  @Provide showNumber: number = 0
  build() {
    Column() {
      Row() {
        Text('showNumber:'+this.showNumber)
          .fontSize(40)
      }
      .width('100%')
      Row() {
      Button('加1').width('100%').height(50).onClick(()=>{
        this.showNumber= this.showNumber+1
      })
      }
      .width('100%')
      Row(){
        Child() // 子组件
      }.width('100%')
    }
    .height('100%')
    .width('100%')

  }
}

子组件:

代码语言:js
复制
@Component
export default struct Child {
@Consume showNumber:number
  build() {
    Column() {
      Row() {
        Text('@Provide装饰器:')
        TextInput({text:JSON.stringify(this.showNumber)})
          .width('100%')
          .type(InputType.Number)
          .height(50)
          .onChange((value)=>{
            if(value){
              this.showNumber=parseInt(value)
            }else  {
              this.showNumber=0
            }
          })
      }
      .width('50%')
    }
  }
}
四 、@Watch装饰器:状态变量更改通知

@Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数

代码语言:js
复制
@Component
struct Child {
  @Prop @Watch('onCountUpdated') count: number = 0;
  @State total: number = 0;
  // @Watch 回调
  onCountUpdated(propName: string): void {
    this.total += this.count;
  }

  build() {
    Text(`Total: ${this.total}`)
  }
}

@Entry
@Component
struct Index {
  @State count: number = 0;

  build() {
    Column() {
      Button('add to basket')
        .onClick(() => {
          this.count++
        })
      Child({ count: this.count })
    }
  }
}
五、@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

对象嵌套两层之后,状态更新失去了响应性,这时候需要用到@Observed装饰器和@ObjectLink装饰器

代码语言:js
复制
// Index.ets
// Child
@Observed
class objA {
  public c: string;

  constructor(c: string) {
    this.c = c;
  }
}
@Observed
class objB {
  public a: objA;
  public b: string;

  constructor(a: objA, b: string) {
    this.a = a;
    this.b = b;
  }
}
@Component
struct Child {
  @ObjectLink a:objA
  build() {
    Text(this.a.c).fontSize(50)
      .onClick(()=>{
        this.a.c = 'ca';  
      })
  }
}
@Entry
@Component
struct Index {
  @State b: objB = new objB(new objA('a'),'b');
  build() {
    Column(){
      Child({a:this.b.a})
    }
    .width('100%')
    .onClick(()=>{
      this.b.a.c='pa'
    })
  }
}

点击父元素,可以实现给b.a.c赋值’pa’;

点击子组件,可以实现给a.c 赋值 ‘ca’

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 鸿蒙next开发中父子组件如何进行数据通信(状态管理v1版)?
    • 【问题描述】:我们经常在开发的时候,需要在父子组件进行数据的传递,有哪几种常见的用法?
    • 【解决方案】:以下几种解决方案可以满足70%的应用场景。
      • 一、@state 和 @prop
      • 二、@state 和 @Link:
      • 三 、@Provide 和 @Consume
      • 四 、@Watch装饰器:状态变量更改通知
      • 五、@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档