常見的5種Vue組件通信方式總結(jié)
引言
在 Vue.js 中,組件通信是開發(fā)過程中非常重要的一部分,它涉及到不同組件之間的數(shù)據(jù)傳遞和交互。本文將介紹如何實(shí)現(xiàn)父子組件之間的有效通信,包括 Props、雙向綁定、ref、以及 provide/inject 這幾種常見的組件通信方式。
1. 父子通信(Props)
在 Vue.js 中,父子組件通信的最基本方式是通過 Props。父組件可以向子組件傳遞數(shù)據(jù)或方法,子組件通過 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):
簡單易懂: Props 是 Vue.js 中最基本的組件通信方式之一,使用簡單直觀,易于理解和上手。
單向數(shù)據(jù)流: 父組件通過 Props 向子組件傳遞數(shù)據(jù),這種單向數(shù)據(jù)流使得數(shù)據(jù)變化的來源清晰明了,便于追蹤和調(diào)試。
組件解耦: 使用 Props 可以讓組件之間保持相對獨(dú)立,提高了組件的可復(fù)用性和可維護(hù)性。
缺點(diǎn):
層級限制: Props 是父子組件之間的通信方式,當(dāng)組件層級較深時,需要逐層傳遞 Props,增加了組件間的耦合性。
大規(guī)模應(yīng)用復(fù)雜性: 在大型應(yīng)用中,如果組件關(guān)系錯綜復(fù)雜,過多的 Props 傳遞會導(dǎo)致代碼不夠清晰,維護(hù)起來較為困難。
數(shù)據(jù)冗余: 有時為了滿足一個子組件的特定需求,需要在父組件中傳遞較多的數(shù)據(jù),可能會導(dǎo)致數(shù)據(jù)冗余或不必要的傳遞。
2. 子父通信($emit)
子組件可以使用 $emit
方法發(fā)布一個事件,父組件可以通過監(jiān)聽這個事件來訂閱,從而實(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)建一個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ù)和消息,子組件可以向父組件傳遞任意類型的數(shù)據(jù)。
解耦合: 子組件通過 $emit 觸發(fā)事件,父組件監(jiān)聽事件,實(shí)現(xiàn)了組件之間的解耦合,提高了組件的獨(dú)立性和復(fù)用性。
響應(yīng)式: 通過 $emit 傳遞的數(shù)據(jù)在父組件中是響應(yīng)式的,可以實(shí)時更新視圖,提高了用戶體驗。
缺點(diǎn):
事件命名沖突: 如果項目較大或組件較多,可能會出現(xiàn)事件命名沖突的情況,需要謹(jǐn)慎管理事件名稱。
跨級通信復(fù)雜性: 當(dāng)組件層級較深時,子組件向父組件傳遞數(shù)據(jù)可能需要經(jīng)過多層中間組件,增加了通信的復(fù)雜性。
不適用于兄弟組件通信: $emit 主要用于子組件向父組件傳遞數(shù)據(jù),對于兄弟組件之間的通信并不直接適用,需要借助其他方式實(shí)現(xiàn)。
3. 子父通信(雙向綁定)
子組件可以通過 $emit
方法將修改后的數(shù)據(jù)發(fā)送給父組件,父組件可以通過 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ù),反之亦然。
簡潔明了: 雙向綁定讓數(shù)據(jù)流動更加清晰明了,減少了手動管理數(shù)據(jù)的復(fù)雜性。
提高開發(fā)效率: 在某些場景下,雙向綁定可以減少編寫大量的事件監(jiān)聽和觸發(fā)邏輯,提高開發(fā)效率。
缺點(diǎn):
數(shù)據(jù)流不清晰: 在復(fù)雜的組件結(jié)構(gòu)中,雙向綁定可能使得數(shù)據(jù)流變得不夠清晰,增加調(diào)試和維護(hù)的難度。
難以追蹤: 當(dāng)數(shù)據(jù)在組件之間頻繁傳遞和修改時,可能會難以追蹤數(shù)據(jù)的變化來源,導(dǎo)致代碼的可讀性降低。
潛在的性能問題: 雙向綁定會引起數(shù)據(jù)的頻繁更新和DOM重新渲染,可能會對性能產(chǎn)生一定的影響,特別是在大型應(yīng)用中。
4. 子父通信(ref)
子組件可以使用 defineExpose
暴露需要共享的值,父組件可以利用 ref
讀取整個子組件對象來獲取暴露的值。
父組件:
- 獲取子組件實(shí)例: 通過在子組件標(biāo)簽上添加 ref 屬性,可以在父組件中來訪問子組件的實(shí)例。
- 直接操作子組件: 父組件可以通過 ref 獲取子組件的實(shí)例,然后直接調(diào)用子組件的方法或訪問子組件的數(shù)據(jù),實(shí)現(xiàn)父組件對子組件的控制和操作。
<!-- 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>
子組件:
- 提供給父組件訪問的接口: 子組件可以通過 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):
直接訪問子組件: 使用 ref 可以直接在父組件中引用和操作子組件的實(shí)例,方便進(jìn)行數(shù)據(jù)傳遞、調(diào)用子組件方法等。
靈活性: ref 提供了一種靈活的方式來處理子組件的數(shù)據(jù)和邏輯,可以根據(jù)具體需求自由地操作子組件。
適用范圍廣泛: ref 不僅可以用于訪問子組件,還可以用于訪問 DOM 元素或其他 Vue 實(shí)例,具有較強(qiáng)的通用性。
缺點(diǎn):
耦合性增加: 直接在父組件中操作子組件的實(shí)例可能會增加組件之間的耦合性,降低了組件的獨(dú)立性和復(fù)用性。
不符合單向數(shù)據(jù)流原則: 使用 ref 可能打破 Vue.js 單向數(shù)據(jù)流的原則,使得數(shù)據(jù)流變得不夠清晰,增加了代碼的復(fù)雜性。
5. 父子組件通信(provide/inject)
父組件可以通過 provide
提供數(shù)據(jù)或方法,子組件可以通過 inject
注入所需的數(shù)據(jù)或方法,實(shí)現(xiàn)父子組件之間的通信。
父組件:
- 使用 provide 來提供數(shù)據(jù),這些數(shù)據(jù)將會被后代組件的 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>
子組件:
- 通過 inject 選項指定需要注入的數(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):
跨層級通信: provide/inject 可以方便地實(shí)現(xiàn)祖先組件向后代組件的數(shù)據(jù)傳遞,解決了跨層級通信問題。
靈活性: provide/inject 不限制數(shù)據(jù)的傳遞方式,提供了一種靈活的組件通信機(jī)制。
減少嵌套組件的復(fù)雜性: 在多層嵌套的組件結(jié)構(gòu)中,provide/inject 可以簡化數(shù)據(jù)傳遞流程,減少了 props 的層層傳遞。
缺點(diǎn):
耦合性增加: 使用 provide/inject 可能會增加組件之間的耦合性,降低了組件的獨(dú)立性和復(fù)用性。
可讀性較差: 在子組件中使用 inject 注入的數(shù)據(jù)需要在組件選項中指定,可讀性相對較差,不如 props 直觀。
以上就是常見的5種Vue組件通信方式總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Vue組件通信方式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue3+element?Plus實(shí)現(xiàn)表格前端分頁完整示例
這篇文章主要給大家介紹了關(guān)于vue3+element?Plus實(shí)現(xiàn)表格前端分頁的相關(guān)資料,雖然很多時候后端會把分頁,搜索,排序都做好,但是有些返回數(shù)據(jù)并不多的頁面,或者其他原因不能后端分頁的通常會前端處理,需要的朋友可以參考下2023-08-08關(guān)于axios配置請求頭content-type實(shí)例詳解
現(xiàn)在前端開發(fā)中需要通過Ajax發(fā)送請求獲取后端數(shù)據(jù)是很普遍的一件事情了,下面這篇文章主要介紹了關(guān)于axios配置請求頭content-type的相關(guān)資料,需要的朋友可以參考下2022-04-04淺談vue項目利用Hbuilder打包成APP流程,以及遇到的坑
這篇文章主要介紹了淺談vue項目利用Hbuilder打包成APP流程,以及遇到的坑,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09詳解Vue3.0中ElementPlus<input輸入框自動獲取焦點(diǎn)>
這篇文章主要給大家介紹了關(guān)于Vue3.0中ElementPlus<input輸入框自動獲取焦點(diǎn)>的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue3.0具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2023-04-04Vue3實(shí)現(xiàn)跨頁面?zhèn)髦档膸追N常見方法
在Vue 3中,跨頁面?zhèn)髦悼梢酝ㄟ^多種方式實(shí)現(xiàn),具體選擇哪種方法取決于應(yīng)用的具體需求和頁面間的關(guān)系,本文列舉了幾種常見的跨頁面?zhèn)髦捣椒?感興趣的同學(xué)跟著小編來看看吧2024-04-04