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

一文让你吃透 Vue3中的组件间通讯 【一篇通】

文章目录

  • 前情回顾
  • 前言
  • 1. 父组件 => 子组件通讯传递
  • 2. 子组件 => 父组件通讯传递
  • 3. 爷孙组件,后代组件通讯数据
  • 总结


前情回顾

在本专栏前一章节中,我为大家带来了 Vue3 新特性变化上手指南 的归纳梳理,主要介绍了 Vue3 的 Proxy 响应式原理,和 Setup (Composition API)的介绍,以及围绕在 Setup (Composition API)基础上的 一些新特性 API 方法,后续我会在此基础上,为大家带来 Vue3 中常见的 一些 API 方法 和新特性知识点 , 开设单独的章节讲解。

前言

大家众所周知,Vue 是一个 拥有组件化编程思想的框架,整个项目程序是由一个一个的 组件块 堆积而成,但是由于 每一个 组件在项目 结构上是完全独立的,但是有时候,我们会面临到的需求是,多个组件之间需要进行数据的交互,也就是说 A 组件里面的数据,需要传递给 B 组件,甚至也可能传递给,更加嵌套深层次的 C组件,D组件等… 那么在 Vue3 中 如何去 实现这些功能,也就是本章节,我要为大家带来的内容!


同样在之前, 我为大家带来过一期,关于在 Vue2 中如何实现 各级组件之间数据通讯的章节讲解,如果有想要了解 在Vue2 中 如何去实现组件之间的 通讯 请点击传送门 Vue2 中的 各级组件通讯

1. 父组件 => 子组件通讯传递

父组件中: 还是和 之前 Vue2 中一样 通过在 子组件 标签上配置自定义属性来传递参数

<template>
    <div class="home">
        <h1>我是父组件</h1>
        <h4>这是将要传给,子组件的数据 ::=>{{ name }}</h4>
        <HelloWorld :namedata="name"></HelloWorld>
    </div>
</template>

<script setup>

import { ref, defineProps, reactive } from "vue"
import HelloWorld from "../../../components/HelloWorld.vue"

let name = ref("你好,vue")
</script>

子组件中:

子组件中, 接收 Props 参数 Vue 提供了一个 新的 API 函数 defineProps() 其使用的方法,就和我们在 Vue2 的子组件中 定义 Props 待接收参数配置一样。
这里需要注意的是,如果我们需要 在 JS 模块中 用到 传递过来的参数, 直接打印会报错,虽然在模板中,可以直接使用,但是在 JS 模块中,我们需要 定义一个 变量 来接收 defineProps() 的返回值,然后再从返回值身上读取。

<template>
  <div class="HelloWorld">
    <h5>我是子级组件</h5>
    <h4>我接收到父组件的 数据 =>{{ namedata }}</h4>
  </div>
</template>

<script setup>
import { defineProps } from "vue"
let receiveProps = defineProps({
  namedata: {
    type: String,
    required: true, //  是否必传
    default: "备用数据", //默认数据
  }
})
console.log(namedata);  //会报错
console.log(receiveProps.namedata);  //不报错

</script>

方式二
如果 你没有 使用 <script setup> Vue3 的语法糖来进行 JS代码块的编写,那么 Setup 函数会接收两个参数,第一个参数就是组件的 Props传递过来的参数。和标准的组件一致,Setup 函数的 Props 是响应式的,并且会在传入新的 Props 时同步更新。

子组件:

<template>
  <div class="HelloWorld">
    <h5>我是子级组件</h5>
    <h4>我接收到父组件的 数据 =>{{ props.namedata }}</h4>
  </div>
</template>

<script>
export default {
  props: {
    namedata: {
      type: String,
      required: true, //  是否必传
      default: "备用数据", //默认数据
    }
  },
  setup(props, context) {
    console.log(props.namedata, context);
    return {
      props
    }
  }
}
</script>

在这里插入图片描述

这里需要注意:
如果你解构了 Props 对象,解构出的变量将会丢失响应性。因此我们推荐通过 props.xxx 的形式来使用其中的 props。
如果你确实需要解构 Props 对象,或者需要将某个 Prop 传到一个外部函数中并保持响应性,那么你可以使用 toRefs() toRef() 这两个工具函数:

import { toRefs, toRef } from 'vue'
export default {
  setup(props) {
    // 将 `props` 转为一个其中全是 ref 的对象,然后解构
    const { title } = toRefs(props)
    // `title` 是一个追踪着 `props.title` 的 ref
    console.log(title.value)
    // 或者,将 `props` 的单个属性转为一个 ref
    const title = toRef(props, 'title')
  }
}

2. 子组件 => 父组件通讯传递

子组件中: 在过去Vue 2中,我们是通过 this.$emit() 添加自定义事件,而在父组件中通过触发自定义事件,来获得传递的参数,但如今在Vue3中 ,为了更好的使用 组合式API ,Vue 已经逐渐的舍去大量的 this 指向了。所以在Setup 中,我们无法访问 this ,对此,Vue3 同样 也为我们提供了 一个新的 API 函数 defineEmits(), 它用来定义要触发的自定义事件函数。

<template>
  <div class="HelloWorld">
    <h5>我是子级组件</h5>
    <el-button type="primary" plain @click="communication">点击给 父组件传递数据</el-button>
    <h3>{{ data }}</h3>
  </div>
</template>

<script setup>

import { defineProps, defineEmits, ref, reactive } from "vue"
let data = ref("这是给父组件的数据")

let emit = defineEmits(["transmit"])

let communication = () => {
  emit("transmit", data)
}
</script>

父组件中 : 在子组件标签体上 注册 所定义自定义事件,并且 触发对应的事件函数,在事件函数中,接收一个参数,就是子组件传递过来的数据。

<template>
    <div class="home">
        <h1>我是父组件</h1>
        <h4>接收到 子组件传给我的 数据 ::=>{{ dataname }}</h4>
        <HelloWorld @transmit="Receive"></HelloWorld>
    </div>
</template>


<script setup>
import { ref, defineProps, reactive, toRef, nextTick } from "vue"
let dataname = ref()
let Receive = (data) => {
    console.log(data);
    dataname.value = data.value
}
</script>

在这里插入图片描述

在这里插入图片描述

3. 爷孙组件,后代组件通讯数据

有时候当我们的组件层次嵌套过深的时候,时常会遇到,跨组件进行数据通讯,如下图:如果父组件需要传递参数给重孙组件呢。这时候,上面的父子组件传参的方式已经不实用了,我们也不可能,去逐层收到数据再逐层进行传递,对此 Vue3 也给我们 提供了两个新的 API 函数 provide()inject() 用来解决这样的需求。

在这里插入图片描述

顶层组件中:

<template>
    <div class="home">
        <h1>我是父组件</h1>
        <h2>{{ name }}</h2>
        <HelloWorld />
    </div>
</template>


<script setup>

import { ref, defineProps, reactive, toRef, nextTick, provide } from "vue"

import HelloWorld from "../../../components/HelloWorld.vue"

let name = ref("这是给重孙组件的数据")

provide("Transferdata", name)  //provide接收两个参数,第一个参数为 和后面接收参数的组件约定好的一个字段名,第二个参数就是要传递的参数。  

</script>


后代组件中

<template>
    <div class="Grandchild">
        <h5>重孙组件</h5>
        <h4>收到:祖先组件的数据{{ Transferdata }}</h4>
        <h4>{{ Transferdata }}</h4>
    </div>
</template>

<script setup>

import { inject } from "vue"

let Transferdata = inject("Transferdata")

</script>

实现:
在这里插入图片描述
provide()inject() 图例:
在这里插入图片描述

注明:以 provide()inject() 这样的方式传递的数据,只要在上层组件中,定义好了,那么无论,它的后代组件嵌套多少层,多么深,后代组件都能够拿取到数据。


补充:
如果组件间的传递 数据量过大,我们更应该选用全局 状态管理库来进行数据共享管理。
点击传送门 解读 在 Vue 中如何搭建全局状态管理库

总结

以上就是本章节为大家带来的 有关在 Vue3 中,如何去使用 组件间的 数据通讯方式。也认识了 几种 新的 API 函数方法。


🚵‍♂️ 博主座右铭:向阳而生,我还在路上!
——————————————————————————————
🚴博主想说:将持续性为社区输出自己的资源,同时也见证自己的进步!
——————————————————————————————
🤼‍♂️ 如果都看到这了,博主希望留下你的足迹!【📂收藏!👍点赞!✍️评论!】
——————————————————————————————


http://www.kler.cn/a/3381.html

相关文章:

  • 日期问题--模板
  • QT6 + CMAKE编译OPENCV3.9
  • 新浪安卓(Android)开发面试题及参考答案(68道题,9道手撕题)
  • K8S中Service详解(三)
  • javaweb之HTML
  • 迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-添加内核编译
  • 【Docker】Compose容器编排LNMP上云
  • IO流你了解多少
  • springboot校友社交系统
  • 机器学习之图像处理——基本概念知识介绍
  • python+appium+pytest自动化测试-参数化设置
  • Qt之实现类似软件安装时的新功能介绍界面
  • Jetson Nano驱动机器人的左右两路电机
  • 安全防御 --- 防火墙
  • 代码随想录算法训练营第五十三天 | 1143.最长公共子序列 1035.不相交的线 53. 最大子序和 动态规划
  • python变量内存管理
  • 古茗科技面试:为什么 ElasticSearch 更适合复杂条件搜索?
  • mysql数据库介绍
  • 基类与派生类对象的关系 派生类的构造函数
  • 【回忆杀】2012年拥有第一台电脑【致逝去的青春】
  • 【MySQL】数据库的约束
  • 中科亿海微FPGA应用(一、点灯)
  • Python | 蓝桥杯进阶第五卷——数论
  • 计算机组成原理|第四章(笔记)
  • 【C语言】动态内存分配malloc,realloc等函数使用和常见错误
  • 【C++】stack|queue|deque(适配器模式)