鸿蒙开发:父组件如何调用子组件中的方法?

程序员一鸣
• 阅读 17

前言

本文基于Api13

很多的场景下,父组件需要触发子组件中的某个方法,来实现一些特定的逻辑,但是ArkUI是声明式UI,不能直接调用子组件中的方法,那么怎么去实现这个功能呢?

举一个很常见的案例,通过调用子组件中的某个方法,实现子组件UI的更新,简单的代码如下,只有通过调用changeUI方法,才会触发UI的更新。

@Component
struct Child {
  @State message: string = "我是子组件"

  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:子组件方法
   */
  changeUI() {
    this.message = "子组件UI更新了"
  }

  build() {
    Text(this.message)
      .width("100%")
      .height(50)
      .backgroundColor(Color.Pink)
      .textAlign(TextAlign.Center)
  }
}

方式一:@Watch装饰器

如果你是用的V1版本装饰器,我们可以使用@Watch装饰器很轻松进行实现。

子组件定义@Watch装饰器

@Component
struct Child {
  @State message: string = "我是子组件"
  @Prop @Watch("changeUI") isChangeStatus: boolean = false

  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:子组件方法
   */
  changeUI() {
    this.message = "子组件UI更新了"
  }

  build() {
    Text(this.message)
      .width("100%")
      .height(50)
      .backgroundColor(Color.Pink)
      .textAlign(TextAlign.Center)
  }
}

父组件调用

可通过子组件定义的isChangeStatus属性,不断的变化其值就可以了。

@Entry
  @Component
  struct DemoPage {
    @State isChangeStatus: boolean = false

    build() {
      Column() {
        Child({ isChangeStatus: this.isChangeStatus })
        Button("点击")
          .onClick(() => {
            this.isChangeStatus = !this.isChangeStatus
          })
      }
      .height('100%')
        .width('100%')
        .justifyContent(FlexAlign.Center)
    }
  }

方式二:@Monitor装饰器

和方式一的实现方式是一致的,只不过,@Monitor装饰器是V2版本,也就是说,你使用的是V2版本装饰器的话,可以使用这个。

子组件定义@Monitor装饰器

@ComponentV2
struct Child {
  @Local message: string = "我是子组件"
  @Param isChangeStatus: boolean = false

  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:子组件方法
   */
  @Monitor("isChangeStatus")
  changeUI() {
    this.message = "子组件UI更新了"
  }

  build() {
    Text(this.message)
      .width("100%")
      .height(50)
      .backgroundColor(Color.Pink)
      .textAlign(TextAlign.Center)
  }
}

父组件调用

@Entry
@ComponentV2
struct DemoPage {
  @Local isChangeStatus: boolean = false

  build() {
    Column() {
      Child({ isChangeStatus: this.isChangeStatus })
      Button("点击")
        .onClick(() => {
          this.isChangeStatus = !this.isChangeStatus
        })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

方式三:接口回调

定义回调函数

class ChangeController {
  change = () => {}
}

子组件实现回调

@Component
struct Child {
  @State message: string = "我是子组件"
  changeController: ChangeController = new ChangeController()

  aboutToAppear(): void {
    if (this.changeController.change != undefined) {
      this.changeController.change = () => {
        this.changeUI()
      }
    }
  }

  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:子组件方法
   */
  changeUI() {
    this.message = "子组件UI更新了"
  }

  build() {
    Text(this.message)
      .width("100%")
      .height(50)
      .backgroundColor(Color.Pink)
      .textAlign(TextAlign.Center)
  }
}

父组件调用函数

@Entry
@Component
struct DemoPage {
  changeController: ChangeController = new ChangeController()

  build() {
    Column() {
      Child({ changeController: this.changeController })
      Button("点击")
        .onClick(() => {
          this.changeController.change()
        })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

方式四:事件订阅EventHub

订阅事件

@Component
struct Child {
  @State message: string = "我是子组件"

  aboutToAppear(): void {
    getContext().eventHub.on("changeUI", ()=>{
      this.changeUI()
    })
  }

  /**
   *AUTHOR:AbnerMing
   *INTRODUCE:子组件方法
   */
  changeUI() {
    this.message = "子组件UI更新了"
  }

  build() {
    Text(this.message)
      .width("100%")
      .height(50)
      .backgroundColor(Color.Pink)
      .textAlign(TextAlign.Center)
  }
}

触发事件

@Entry
@Component
struct DemoPage {
  build() {
    Column() {
      Child()
      Button("点击")
        .onClick(() => {
          getContext().eventHub.emit('changeUI')
        })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

相关总结

也许大家可能会有疑问,子组件更新UI,直接由装饰器触发不就行了,希望大家能够明白,以上呢只是简单的案例,在实际的开发中,子组件方法中可能很多的逻辑,比如网络请求,比如数据存储等等,并不是简单的UI更新。

当然了,所举的实现方式也不是全的,可能也有着其它的方式可以实现,大家在实际的开发中选择适合的一种即可。

点赞
收藏
评论区
推荐文章
晴空闲云 晴空闲云
3年前
vue3中基于script setup语法糖的$refs使用
在用vue3开发项目的时候,需要调用子组件的方法,于是想着用$refs来实现,但是我是使用scriptsetup语法糖,原先vue2的语法已经不适用了。于是一番折腾和查阅资料,终于搞定。vue2语法vue2语法在组件上设置ref属性后,在代码里可以通过this.$refs.ref值访问到对应的子组件。一个设置ref值的组件:html在js代码中可以通
Alex799 Alex799
3年前
vue最新面试题
最近在面试,总结几个重点的面试题:一、vue父子组件之间的传值:简单来说,子组件通过props方法接受父组件传来的值,子组件通过$emit方法来向父组件发送数据。(具体案例可以看我之前写的博客)。二、vue生命周期函数:beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestr
Chase620 Chase620
4年前
vue的8种通信方式
1.props/emit1.父组件向子组件传值下面通过一个例子说明父组件如何向子组件传递数据:在子组件article.vue中如何获取父组件section.vue中的数据articles:\'红楼梦','西游记','三国演义'\//section父组件<template<divclass"section"
Easter79 Easter79
3年前
tomcat系列之五:Tomcat各个组件生命周期
一,Tomcat中各个组件的关系1,组件有大有小,大组件管理小组件。比如Server管理Service,Service管理连接器和容器2,组件有内有外,外层组件控制内层组件。比如外层组件连接器负责对外交流,外层组件调用内层组件完成业务功能二,创建组件的顺序先创建子组件,再创建父组件,然后把子组件注入到父组件中先创建内层组件,再创建外层
浩浩 浩浩
4年前
【Flutter实战】对齐与相对定位(Align)
4.6对齐与相对定位(Align)在上一节中我们讲过通过Stack和Positioned,我们可以指定一个或多个子元素相对于父元素各个边的精确偏移,并且可以重叠。但如果我们只想简单的调整一个子元素在父元素中的位置的话,使用Align组件会更简单一些。4.6.1AlignAlign组件可以调整子组件的位置,并且可以根据子
LinMeng LinMeng
4年前
Chase620 Chase620
4年前
关于:父组件中的子组件中的子组件(孙级)添加数据后怎么样去调用父组件中的方法呢?
1、需求引入image.png这是父组件下的子组件的子组件,一个绑定子设备的弹出窗modal,那么我们怎么样在这个组件中选中子设备后点击确定时去触发父组件的父组件的table列表数据刷新呢?image.pngimage.pngimage.png组件的层级关系.png上述的图示便是部分代码的展示,一般的组件传值有父组件传子组件(
Stella981 Stella981
3年前
Flutter子组件调用父组件方法修改父组件参数
子组件调用父级组件方法的主要实现是父组件给子组件传入一个方法,然后在子组件中调用父级方法来修改父级的参数。看一下效果图!(https://img2018.cnblogs.com/blog/1038765/201907/103876520190702152130487420290106.gif)父级组件实现在父级组件中写一个
京东云开发者 京东云开发者
7个月前
鸿蒙跨端实践-ArkTS和CAPI的混合开发实现
一、背景在文章中,讲述了动态化适配鸿蒙的方案实现,当在鸿蒙系统进行UI渲染的时候,我们使用了系统的组件进行递归渲染。在iOS和Android也是借助各自系统组件进行的渲染,但是在鸿蒙系统会存在以下4个严重问题:1.UI层级过多以金融APP理财频道页中的一个
昔不亏 昔不亏
4个月前