Vue基础——组件通信方式

1.引言

在Vue中,组件通信是非常重要的一个主题,它涉及到不同组件之间的数据交换和消息传递,而Vue提供了多种方式来实现组件间的通讯。本文将从父子组件通信和子父组件通信两个方面进行介绍。

1.1 引入案例介绍

这个案例非常简单,总共分为2部分,第一部分由一个input框和一个button按钮组成,第二部分通过ul、li进行数据渲染。

<template>
    <!-- 第一部分 -->
    <div class="input-group">
        <input type="text" v-model="value">
        <button @click="add">添加</button>
    </div>
    <!-- 第二部分 -->
    <div class="child">
        <ul>
            <li v-for="item in list">{{ item }}</li>
        </ul>
    </div>
</template>

<script setup>
import { ref } from 'vue';

const list = ref(['red', 'green', 'black']);
const value = ref('');

const add = () => {
    if (value.value !== '') {
        list.value.push(value.value);
        value.value = '';
    }
}
</script>

<style lang="scss" scoped></style>

image.png

下面我们将分别将第一部分和第二部分作为子组件来讲解vue中组件通信的方式。

2.父子组件通信(父组件传输数据给子组件)

创建一个新的vue文件(child.vue),将原vue文件(App.vue)的第二部分移至新文件中,再将新vue import到原vue文件中。

这样App.vue就是父组件,child.vue则是子组件。

2.1 情景一:子组件只进行数据渲染

2.1.1 父组件发送数据

父组件通过v-bind绑定将数据发送给子组件

image.png

  • <Child>:父组件中子组件的声明
  • :list="list":list 是一种简写形式,等同于 v-bind:list,用于将父组件的数据 list 绑定到子组件的 list 属性。
  • list:传递给子组件的数据名称,即父组件中定义的变量名。父组件中的 list 变量通过这种方法传递给了子组件。

子组件在接收到这个数据后,根据需要对其进行渲染。

2.1.2 子组件接收数据

子组件通过defineProps来接收数据。

image.png

  • 使用 defineProps 定义接收 list 作为属性。
  • 设置 list 的类型为数组,并提供默认值为空数组。
  • 如果传输数据不是Array,则报错

2.2 情景二:子组件进行数据渲染 + 数据增加

与情景一不同的是父组件只需要将input添加的字符串传输给子组件,而不需要传输整个list数组。

2.2.1 父组件发送数据

image.png

创建一个新的变量toChild来存储input框里输入的值,并通过msg prop 来传递这个数据。

2.2.2 子组件接收数据

image.png

  • 此情景下的defineProps是相对于情景一的简写,不会对传输的数据类型进行校验。

  • watch(() => props.msg, (newVal, oldVal) => { ... }):

    • () => props.msg:使用箭头函数返回 props.msg 的值,即监视 props.msg 的变化。
    • (newVal, oldVal) => { ... }:回调函数,当 props.msg 变化时被触发。newVal 表示新的值,oldVal 表示之前的值。
  • (newVal, oldVal) => { list.value.push(newVal); }:

    • 在回调函数中,当 props.msg 发生变化时(新值为 newVal),将新值添加到 list 数组中。

当父组件传递给子组件的 msg 数据发生变化时,通过 watch 监听该变化,并将新值添加到子组件内部的 list 数组中。这样就实现了响应式地更新子组件中展示的列表数据,保持数据同步和反应性。

如果不使用watch,父组件传输的值永远为 '' 空字符串,在点击添加button后也不会再次再次响应。

3.子父组件通信

创建一个新的vue文件(child.vue),将原vue文件(App.vue)的第一部分移至新文件中,再将新vue import到原vue文件中。

这样App.vue就是父组件,child.vue则是子组件。

3.1 方式一:发布订阅机制

借助发布订阅机制,子组件负责发布事件并携带参数,父组件订阅该事件通过事件参数获取子组件提供的值。

3.1.1 子组件发送数据——仅发送input的value

子组件需要将input的value传递给父组件。

image.png

  • const emits = defineEmits(['add1']);

    • defineEmits 是一个 Vue 3 Composition API 提供的函数,用于定义子组件可以发出的自定义事件。
    • 在这里,通过 defineEmits(['add1']) 定义了一个名为 add1 的自定义事件。
  • emits('add1', value.value);:调用 emits 函数,通过名称 'add1' 发出一个名为add1的自定义事件,并传递 value.value 作为事件的数据。

3.1.2 父组件接收数据

image.png

  • <Child @add1="handle"></Child>: 监听 add1 事件,事件触发时执行 handle 方法。
  • event为子组件发布事件时传递的事件数据

3.2 方式二:v-model

父组件借助v-model将数据绑定给子组件,子组件创建'updata:xxx'事件,并将接收到的数据修改后emits出来

3.2.1 子组件发送数据——发送整个list

image.png

  • 通过 defineEmits 定义了一个名为 emits 的对象,其中包含了一个名为 update:list 的事件。
  • const arr = props.list;:创建一个指向父组件传递的 list 数据的引用。
  • arr.push(value.value);:将当前组件内部的 value 值添加到 arr 数组中。
  • emits('update:list', arr);:通过 emits 触发 update:list 的事件,并传递修改后的 arr 数组,新的数据传递给父组件。

为什么不使用更为简单的 props.list.push(value.value)?

  1. 单向数据流
  • Vue 中的 props 是单向数据流的,即父组件向子组件传递数据,子组件应当尽量避免直接修改父组件传递的 props 数据。这是为了维持数据流的清晰性和可预测性。
  1. 避免数据混乱和副作用
  • 当直接在子组件中修改 props 时,可能导致意外的数据变化,特别是在大型应用中很难追踪数据变化的来源。这样的操作会增加代码的复杂性和出错的可能性。
3.2.2 父组件接收数据

image.png

  • v-model:list="list":将 list 作为 v-model 绑定到 Child 子组件,这意味着 Child 组件可以修改和更新 list 的值。

3.3 方式三:ref

父组件通过ref获取子组件中的defineExpose() 暴露出来的数据。

3.3.1 子组件发送数据——发送整个list

image.png

  • 使用 defineExpose 暴露 list 属性,使父组件能够通过 childRef 访问到子组件中的 list
3.3.2 父组件接收数据

image.png

  • Child 组件被渲染并通过 ref 属性绑定到 childRef 引用。
  • 使用 ref 创建一个 childRef,初始值为 null,用于引用子组件实例。

结语

通过上述介绍,我们可以看到在Vue中实现组件通讯有多种方式,开发者可以根据具体的场景和需求选择适合的方式来进行组件通讯,从而实现更灵活和高效的前端开发。希望本文能对大家有所帮助,感谢阅读!

原文:https://juejin.cn/post/7384327143785381939

  • 13
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值