常見(jiàn)的5種Vue組件通信方式總結(jié)
引言
在 Vue.js 中,組件通信是開(kāi)發(fā)過(guò)程中非常重要的一部分,它涉及到不同組件之間的數(shù)據(jù)傳遞和交互。本文將介紹如何實(shí)現(xiàn)父子組件之間的有效通信,包括 Props、雙向綁定、ref、以及 provide/inject 這幾種常見(jiàn)的組件通信方式。
1. 父子通信(Props)
在 Vue.js 中,父子組件通信的最基本方式是通過(guò) Props。父組件可以向子組件傳遞數(shù)據(jù)或方法,子組件通過(guò) props 接收這些數(shù)據(jù),從而實(shí)現(xiàn)父子組件之間的通信。

父組件:
<!-- Parent.vue -->
<template>
<div class="hd">
<input type="text" name="" id="" v-model="msg">
<button @click="add">添加 </button>
</div>
<Child :list="list" />
</template>
<script setup>
import { ref } from 'vue'
import Child from './components/Child.vue'
const list = ref(['html', 'css'])
const msg = ref('')
const add = () => {
list.value.push(msg.value)
}
</script>
子組件:
<!-- Child.vue -->
<template>
<div class="bd">
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
defineProps({
list: {
type: Array,
default: () => []
}
})
</script>
父子通信(Props)的優(yōu)點(diǎn)和缺點(diǎn)如下:
優(yōu)點(diǎn):
簡(jiǎn)單易懂: Props 是 Vue.js 中最基本的組件通信方式之一,使用簡(jiǎn)單直觀,易于理解和上手。
單向數(shù)據(jù)流: 父組件通過(guò) Props 向子組件傳遞數(shù)據(jù),這種單向數(shù)據(jù)流使得數(shù)據(jù)變化的來(lái)源清晰明了,便于追蹤和調(diào)試。
組件解耦: 使用 Props 可以讓組件之間保持相對(duì)獨(dú)立,提高了組件的可復(fù)用性和可維護(hù)性。
缺點(diǎn):
層級(jí)限制: Props 是父子組件之間的通信方式,當(dāng)組件層級(jí)較深時(shí),需要逐層傳遞 Props,增加了組件間的耦合性。
大規(guī)模應(yīng)用復(fù)雜性: 在大型應(yīng)用中,如果組件關(guān)系錯(cuò)綜復(fù)雜,過(guò)多的 Props 傳遞會(huì)導(dǎo)致代碼不夠清晰,維護(hù)起來(lái)較為困難。
數(shù)據(jù)冗余: 有時(shí)為了滿足一個(gè)子組件的特定需求,需要在父組件中傳遞較多的數(shù)據(jù),可能會(huì)導(dǎo)致數(shù)據(jù)冗余或不必要的傳遞。
2. 子父通信($emit)
子組件可以使用 $emit 方法發(fā)布一個(gè)事件,父組件可以通過(guò)監(jiān)聽(tīng)這個(gè)事件來(lái)訂閱,從而實(shí)現(xiàn)子父組件之間的通信。

子組件:
<!-- Child.vue -->
<template>
<div class="hd">
<input type="text" name="" id="" v-model="msg">
<button @click="add">添加</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('')
const emits = defineEmits(['add']) //創(chuàng)建一個(gè)add事件
const add = () => {
emits('add', msg.value);
console.log(msg.value);
msg.value = '';
}
</script>
父組件:
<!-- Parent.vue -->
<template>
<Child @add="handle" />
<div class="bd">
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child.vue'
const list = ref(['html', 'css'])
const handle = (e) => {
list.value.push(e)
}
</script>
子父通信($emit)的優(yōu)點(diǎn)和缺點(diǎn)如下:
優(yōu)點(diǎn):
靈活性: 使用 $emit 實(shí)現(xiàn)子父通信可以非常靈活地傳遞數(shù)據(jù)和消息,子組件可以向父組件傳遞任意類(lèi)型的數(shù)據(jù)。
解耦合: 子組件通過(guò) $emit 觸發(fā)事件,父組件監(jiān)聽(tīng)事件,實(shí)現(xiàn)了組件之間的解耦合,提高了組件的獨(dú)立性和復(fù)用性。
響應(yīng)式: 通過(guò) $emit 傳遞的數(shù)據(jù)在父組件中是響應(yīng)式的,可以實(shí)時(shí)更新視圖,提高了用戶體驗(yàn)。
缺點(diǎn):
事件命名沖突: 如果項(xiàng)目較大或組件較多,可能會(huì)出現(xiàn)事件命名沖突的情況,需要謹(jǐn)慎管理事件名稱。
跨級(jí)通信復(fù)雜性: 當(dāng)組件層級(jí)較深時(shí),子組件向父組件傳遞數(shù)據(jù)可能需要經(jīng)過(guò)多層中間組件,增加了通信的復(fù)雜性。
不適用于兄弟組件通信: $emit 主要用于子組件向父組件傳遞數(shù)據(jù),對(duì)于兄弟組件之間的通信并不直接適用,需要借助其他方式實(shí)現(xiàn)。
3. 子父通信(雙向綁定)
子組件可以通過(guò) $emit 方法將修改后的數(shù)據(jù)發(fā)送給父組件,父組件可以通過(guò) v-model 在子組件上實(shí)現(xiàn)雙向綁定,實(shí)現(xiàn)父子組件之間數(shù)據(jù)的雙向同步。
父組件:
<!-- Parent.vue -->
<template>
<Child v-model:list="list" />
<div class="bd">
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './components/Child.vue'
const list = ref(['html', 'css'])
</script>
子組件:
<!-- Child.vue -->
<template>
<div class="hd">
<input type="text" name="" id="" v-model="msg">
<button @click="add">添加</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('')
const props = defineProps({
list: {
type: Array,
default: () => []
}
})
const emits = defineEmits(['update:list'])
const add = () => {
const arr = props.list
arr.push(msg.value)
emits('update:list', arr)
msg.value = ''
}
</script>
子父通信(雙向綁定)
優(yōu)點(diǎn):
數(shù)據(jù)同步: 使用雙向綁定可以實(shí)現(xiàn)數(shù)據(jù)的雙向同步,子組件修改數(shù)據(jù)后可以直接影響到父組件中的數(shù)據(jù),反之亦然。
簡(jiǎn)潔明了: 雙向綁定讓數(shù)據(jù)流動(dòng)更加清晰明了,減少了手動(dòng)管理數(shù)據(jù)的復(fù)雜性。
提高開(kāi)發(fā)效率: 在某些場(chǎng)景下,雙向綁定可以減少編寫(xiě)大量的事件監(jiān)聽(tīng)和觸發(fā)邏輯,提高開(kāi)發(fā)效率。
缺點(diǎn):
數(shù)據(jù)流不清晰: 在復(fù)雜的組件結(jié)構(gòu)中,雙向綁定可能使得數(shù)據(jù)流變得不夠清晰,增加調(diào)試和維護(hù)的難度。
難以追蹤: 當(dāng)數(shù)據(jù)在組件之間頻繁傳遞和修改時(shí),可能會(huì)難以追蹤數(shù)據(jù)的變化來(lái)源,導(dǎo)致代碼的可讀性降低。
潛在的性能問(wèn)題: 雙向綁定會(huì)引起數(shù)據(jù)的頻繁更新和DOM重新渲染,可能會(huì)對(duì)性能產(chǎn)生一定的影響,特別是在大型應(yīng)用中。
4. 子父通信(ref)
子組件可以使用 defineExpose 暴露需要共享的值,父組件可以利用 ref 讀取整個(gè)子組件對(duì)象來(lái)獲取暴露的值。
父組件:
- 獲取子組件實(shí)例: 通過(guò)在子組件標(biāo)簽上添加 ref 屬性,可以在父組件中來(lái)訪問(wèn)子組件的實(shí)例。
- 直接操作子組件: 父組件可以通過(guò) ref 獲取子組件的實(shí)例,然后直接調(diào)用子組件的方法或訪問(wèn)子組件的數(shù)據(jù),實(shí)現(xiàn)父組件對(duì)子組件的控制和操作。
<!-- Parent.vue -->
<template>
<Child ref="childRef" />
<div class="bd">
<ul>
<li v-for="item in childRef?.list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import Child from './components/Child_4.vue'
const childRef = ref(null)
</script>
子組件:
- 提供給父組件訪問(wèn)的接口: 子組件可以通過(guò) ref 方法提供自身的實(shí)例給父組件,使得父組件可以直接操作子組件。
<!-- Child.vue -->
<template>
<div class="hd">
<input type="text" name="" id="" v-model="msg">
<button @click="add">添加</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const list = ref(['html', 'css'])
const msg = ref('')
const add = () => {
list.value.push(msg.value)
msg.value = ''
}
defineExpose({ list }) //子組件暴露出去的數(shù)據(jù)
</script>
子父通信(ref)優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):
直接訪問(wèn)子組件: 使用 ref 可以直接在父組件中引用和操作子組件的實(shí)例,方便進(jìn)行數(shù)據(jù)傳遞、調(diào)用子組件方法等。
靈活性: ref 提供了一種靈活的方式來(lái)處理子組件的數(shù)據(jù)和邏輯,可以根據(jù)具體需求自由地操作子組件。
適用范圍廣泛: ref 不僅可以用于訪問(wèn)子組件,還可以用于訪問(wèn) DOM 元素或其他 Vue 實(shí)例,具有較強(qiáng)的通用性。
缺點(diǎn):
耦合性增加: 直接在父組件中操作子組件的實(shí)例可能會(huì)增加組件之間的耦合性,降低了組件的獨(dú)立性和復(fù)用性。
不符合單向數(shù)據(jù)流原則: 使用 ref 可能打破 Vue.js 單向數(shù)據(jù)流的原則,使得數(shù)據(jù)流變得不夠清晰,增加了代碼的復(fù)雜性。
5. 父子組件通信(provide/inject)
父組件可以通過(guò) provide 提供數(shù)據(jù)或方法,子組件可以通過(guò) inject 注入所需的數(shù)據(jù)或方法,實(shí)現(xiàn)父子組件之間的通信。

父組件:
- 使用 provide 來(lái)提供數(shù)據(jù),這些數(shù)據(jù)將會(huì)被后代組件的 inject 所接收。
<!-- Parent.vue -->
<template>
<div class="hd">
<input type="text" name="" id="" v-model="msg">
<button @click="add">添加</button>
</div>
<Child />
</template>
<script setup>
import { ref, provide } from 'vue';
import Child from './components/Child5.vue'
const msg = ref('')
const list = ref(['html', 'css'])
provide('list', list.value)
const add = () => {
list.value.push(msg.value)
}
</script>
子組件:
- 通過(guò) inject 選項(xiàng)指定需要注入的數(shù)據(jù),可以從父組件中接收到共享的數(shù)據(jù)。
<!-- Child.vue -->
<template>
<div class="bd">
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
<Child5 />
</div>
</template>
<script setup>
import { ref, inject } from 'vue';
const list = inject('list');
</script>
父子組件通信(provide/inject)優(yōu)點(diǎn)和缺點(diǎn):
優(yōu)點(diǎn):
跨層級(jí)通信: provide/inject 可以方便地實(shí)現(xiàn)祖先組件向后代組件的數(shù)據(jù)傳遞,解決了跨層級(jí)通信問(wèn)題。
靈活性: provide/inject 不限制數(shù)據(jù)的傳遞方式,提供了一種靈活的組件通信機(jī)制。
減少嵌套組件的復(fù)雜性: 在多層嵌套的組件結(jié)構(gòu)中,provide/inject 可以簡(jiǎn)化數(shù)據(jù)傳遞流程,減少了 props 的層層傳遞。
缺點(diǎn):
耦合性增加: 使用 provide/inject 可能會(huì)增加組件之間的耦合性,降低了組件的獨(dú)立性和復(fù)用性。
可讀性較差: 在子組件中使用 inject 注入的數(shù)據(jù)需要在組件選項(xiàng)中指定,可讀性相對(duì)較差,不如 props 直觀。
以上就是常見(jiàn)的5種Vue組件通信方式總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Vue組件通信方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用wang-editor上傳圖片后端接收不到的問(wèn)題解決
這篇文章主要介紹了如何解決wang-editor 上傳圖片后端接收不到的問(wèn)題,文中通過(guò)圖文結(jié)合給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-02-02
vue3+element?Plus實(shí)現(xiàn)表格前端分頁(yè)完整示例
這篇文章主要給大家介紹了關(guān)于vue3+element?Plus實(shí)現(xiàn)表格前端分頁(yè)的相關(guān)資料,雖然很多時(shí)候后端會(huì)把分頁(yè),搜索,排序都做好,但是有些返回?cái)?shù)據(jù)并不多的頁(yè)面,或者其他原因不能后端分頁(yè)的通常會(huì)前端處理,需要的朋友可以參考下2023-08-08
關(guān)于axios配置請(qǐng)求頭content-type實(shí)例詳解
現(xiàn)在前端開(kāi)發(fā)中需要通過(guò)Ajax發(fā)送請(qǐng)求獲取后端數(shù)據(jù)是很普遍的一件事情了,下面這篇文章主要介紹了關(guān)于axios配置請(qǐng)求頭content-type的相關(guān)資料,需要的朋友可以參考下2022-04-04
淺談vue項(xiàng)目利用Hbuilder打包成APP流程,以及遇到的坑
這篇文章主要介紹了淺談vue項(xiàng)目利用Hbuilder打包成APP流程,以及遇到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
詳解Vue3.0中ElementPlus<input輸入框自動(dòng)獲取焦點(diǎn)>
這篇文章主要給大家介紹了關(guān)于Vue3.0中ElementPlus<input輸入框自動(dòng)獲取焦點(diǎn)>的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue3.0具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-04-04
vue中keep-alive多級(jí)路由緩存問(wèn)題
本文主要介紹了vue中keep-alive多級(jí)路由緩存問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
Vue3實(shí)現(xiàn)跨頁(yè)面?zhèn)髦档膸追N常見(jiàn)方法
在Vue 3中,跨頁(yè)面?zhèn)髦悼梢酝ㄟ^(guò)多種方式實(shí)現(xiàn),具體選擇哪種方法取決于應(yīng)用的具體需求和頁(yè)面間的關(guān)系,本文列舉了幾種常見(jiàn)的跨頁(yè)面?zhèn)髦捣椒?感興趣的同學(xué)跟著小編來(lái)看看吧2024-04-04

