vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue父子组件通讯

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

作者:睡着学

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

父子组件通讯

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

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

在这个demo中:

//组件一
<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父子组件通讯的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文