Vue父子组件通讯的四种方法详解

 更新时间:2024年07月03日 08:39:59   作者:睡着学  
父子组件通讯是指在前端开发的组件化架构中,父组件与子组件之间互相传递数据和触发功能的一种机制,这种机制使得组件能够保持独立性的同时,也能协同工作,本文给大家介绍了Vue父子组件通讯的四种方法,需要的朋友可以参考下

父子组件通讯

父子组件通讯是指在前端开发的组件化架构中,父组件与子组件之间互相传递数据和触发功能的一种机制。这种机制使得组件能够保持独立性的同时,也能协同工作,完成复杂的界面逻辑和数据交互。

通过一个用vue实现的demo为例:

在这个demo中:

  • 需要使用v-model指令将文本框内的内容与变量进行双向绑定,用于获取文本框内的内容。
  • 通过一个数组存储需要展示的内容,并且使用v-for遍历数组内的内容然后渲染。
  • 通过@click='add'为按钮添加一个点击事件将文本框的输入内容添加到数组上。
//组件一
<div class="input-group">
    <input type="text" v-model="item">
    <button @click="add">添加</button>
</div>
//组件二(需要数据)
<div class="child">
    <ul>
        <li v-for="item in list">{{ item }}</li>
    </ul>
</div>

如果我们将组件一放在父组件内,将组件二放在子组件,那我们要怎么将父组件中数据传递给子组件进行渲染呢?(组件二需要数据

这个时候就需要进行父子组件的通讯。

父向子通讯

父组件向子组件传递信息非常方便,通过子组件的属性传递数据就好了。

组件一放在父组件,组件二放在子组件中。父组件将值v-bind绑定传给子组件,子组件使用defineProps接受。

父组件:在<Child :toChild="toChild"></Child>中用v-bind绑定toChild变量传递给子组件。

<template>
<div class="input-group">
    <input type="text" v-model="item">
    <button @click="add">添加</button>
    </div>
//将数据传递给子组件
<Child :toChild="toChild"></Child>
</template>
<script setup>
    import Child from '@/components/child1.vue'
    import { ref } from "vue";
    const item = ref('')
    const toChild = ref('')
    const add = () => {
        toChild.value = item.value
        item.value = ''
    }
</script>

子组件:子组件用defineProps接受父组件传递的数据并且通过设置一个watch监听器,当父组件通过toChild属性传递一个新的值,这个值就会被添加到子组件的列表中。

<template>
<div class="child">
    <ul>
        <li v-for="item in list">{{ item }}</li>
    </ul>
    </div>
</template>
<script setup>
    import { defineProps } from 'vue'
    import { reactive, watch } from "vue";
    const list = reactive(['html', 'css', 'javascript'])
    //接收父组件的数据
    const props = defineProps({
        toChild: ''
    })
    //监听数据的改变动态添加到数组里
    watch(() => props.toChild, (newVal, oldVal) => {
        list.push(newVal)
    })
</script>

子向父通讯

子组件向父组件传递数据较为麻烦一点,常见的方法是通过自定义事件实现数据的传递。

将组件二放在父组件,将组件一放在子组件里。

方法一

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

子组件:通过defineEmits定义并创建一个add事件,再通过触发点击事件的处理函数用emits发布add事件,并且携带数据。

<template>
<div class="input-group">
    <input type="text" v-model="item">
    <button @click="add">添加</button>
    </div>
</template>
<script setup>
    import { ref } from "vue";
    const item = ref('')
    const emits = defineEmits(['add'])//创建一个add事件
    const add = () => {
        //将item变量给到父组件
        emits('add', item.value)//发布add事件
        item.value = ''
    }
</script>

父组件:通过<child @add="handle"></child>给子组件绑定自定义的add事件并且以handle函数作为处理函数。当add事件发布时,就会触发执行handle函数并且通过handle函数的参数接收子组件传递的数据。

<template>
<!-- 订阅add事件,子组件什么时候发布add事件,父组件就会执行handle函数,从而实现数据的共享 -->
<child @add="handle"></child>
<div class="child">
    <ul>
        <li v-for="item in list">{{ item }}</li>
    </ul>
    </div>
</template>
<script setup>
    import child from '@/components/child2.vue'
    import { reactive } from "vue";
    const list = reactive(['html', 'css', 'javascript'])
    const handle = (value) => {
        list.push(value)
    }
</script>

这种方法中子组件只需要发布自定义事件并且携带数据,父组件只需要监听自定义事件并且接受数据。

方法二

父组件借助v-model将数据绑定给子组件,子组件创建update:xxx事件,并接收到该数据将修改后的数据emits(发布)出来让父组件接收修改后的数据。

父组件:在<child v-model:list="list"></child>中,使用v-model:list 将父组件中的 list 数据(渲染数组)传递给子组件并且进行绑定,当子组件发布 update:list 事件后,父组件将接收到修改后的渲染数组并且进行重新渲染。

<template>
<div>
    <child v-model:list="list"></child>
    <div class="child">
        <ul>
            <li v-for="item in list">{{ item }}</li>
    </ul>
    </div>
    </div>
</template>
<script setup>
    import child from '@/components/child3.vue'
    import {reactive } from "vue";
    const list = reactive(['html', 'css', 'javascript'])
</script>

子组件:子组件通过defineProps接收父组件发送的list,并且自定义一个Update:list事件。当点击按钮后触发add函数,将文本框数据放入list中,然后发布Update:list事件并且携带着修改后的list。随着Update:list事件的发布,父组件就可以接收到修改后的list

<template>
<div>
    <div class="input-group">
        <input type="text" v-model="item">
        <button @click="add">添加</button>
    </div>
    </div>
</template>
<script setup>
    import { ref } from "vue";
    const item = ref('')
    const props = defineProps({
        list: {
            type: Array,
            default: () => []
        }
    })
    const emits = defineEmits(['Update:list'])
    const add = () => {
        const arr = props.list
        arr.push(item.value)
        emits('Update:list', arr)
        item.value = ''
    }
</script>

这种方法使父组件的操作变得简洁,但将子组件的操作变得复杂了。父组件只需要和子组件进行双向绑定数据就行了,子组件则需要接收数据再发布自定义的Update:xxx事件将修改后的数据传递给父组件。

方法三

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

子组件:使用 defineExpose 暴露数据,子组件通过defineExpose({ list })将更新后的渲染数组暴露给父组件。

<template>
<div class="input-group">
    <input type="text" v-model="item">
    <button @click="add">添加</button>
    </div>
</template>
<script setup>
    import { ref, reactive } from "vue";
    const item = ref('')
    const list = reactive(['html', 'css', 'javascript'])
    const add = () => {
        list.push(item.value)
        item.value = ''
    }
    defineExpose({ list })
</script>

父组件:获取子组件的数据,使用 ref 定义一个引用变量来引用子组件,并在适当的时机获取子组件暴露的渲染数组。将子组件暴露的渲染数组作为v-for的循环对象进行渲染。

<template>
//获取子组件的引用
<child ref="childRef"></child>
<div class="child">
    <ul>
        //childRef?.list表示只有在在子组件已经挂载完成后才能访问子组件暴露的list数据
        <li v-for="item in childRef?.list">{{ item }}</li>
    </ul>
    </div>
</template>
<script setup>
    import child from '@/components/child4.vue'
    import { ref, reactive, onMounted } from "vue";
    //用ref定义一个引用变量
    const childRef = ref(null);
</script>

这种方法十分简便,子组件只需要暴露数据给父组件,然后父组件引用子组件暴露的数据,但是需要注意生命周期,需要在组件挂载完成后父组件才能成功获取子组件的数据。

以上就是Vue父子组件通讯的四种方法详解的详细内容,更多关于Vue父子组件通讯的资料请关注脚本之家其它相关文章!

相关文章

  • vue技术分享之你可能不知道的7个秘密

    vue技术分享之你可能不知道的7个秘密

    这篇文章主要介绍了vue技术分享-你可能不知道的7个秘密,需要的朋友可以参考下
    2018-04-04
  • Vue 响应式系统依赖收集过程原理解析

    Vue 响应式系统依赖收集过程原理解析

    Vue 初始化时就会通过 Object.defineProperty 拦截属性的 getter 和 setter ,为对象的每个值创建一个 dep 并用 Dep.addSub() 来存储该属性值的 watcher 列表,这篇文章主要介绍了Vue 响应式系统依赖收集过程分析,需要的朋友可以参考下
    2022-06-06
  • Vue 富文本编辑器tinymce的安装配置使用教程

    Vue 富文本编辑器tinymce的安装配置使用教程

    TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,由JavaScript写成,TinyMCE是一个根据LGPL license发布的自由软件,你可以把它用于商业应用,这篇文章主要介绍了Vue 富文本编辑器tinymce的安装教程,需要的朋友可以参考下
    2023-09-09
  • vue项目中onscroll的坑及解决

    vue项目中onscroll的坑及解决

    这篇文章主要介绍了vue项目中onscroll的坑及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • element table 数据量大页面卡顿的解决

    element table 数据量大页面卡顿的解决

    这篇文章主要介绍了element table 数据量大页面卡顿的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • vue+element+Java实现批量删除功能

    vue+element+Java实现批量删除功能

    这篇文章主要介绍了vue+element+Java实现批量删除功能,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04
  • vue如何定义全局变量和全局方法实例代码

    vue如何定义全局变量和全局方法实例代码

    在项目中经常会复用一些变量和函数,比如用户的登录token,用户信息等,这时将它们设为全局的就显得很重要了,下面这篇文章主要给大家介绍了关于vue如何定义全局变量和全局方法的相关资料,需要的朋友可以参考下
    2023-04-04
  • web前端vue之CSS过渡效果示例

    web前端vue之CSS过渡效果示例

    本篇文章主要介绍了web前端vue之CSS过渡效果示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • vue集成openlayers问题

    vue集成openlayers问题

    这篇文章主要介绍了vue集成openlayers问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • vue-cli4创建项目导入Element-UI踩过的坑及解决

    vue-cli4创建项目导入Element-UI踩过的坑及解决

    这篇文章主要介绍了vue-cli4创建项目导入Element-UI踩过的坑及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04

最新评论