Vue3實(shí)現(xiàn)組件通信的14種方式詳解與實(shí)戰(zhàn)
一、父子組件通信
1. props 父?jìng)髯?/h3>
適用場(chǎng)景:父組件向子組件傳遞數(shù)據(jù)
核心用法:defineProps 接收 props
<!-- 父組件 Parent.vue -->
<template>
<Child :message="parentMsg" />
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const parentMsg = ref('Hello from Parent');
</script>
<!-- 子組件 Child.vue -->
<template>
<div>父組件傳遞的props: {{ message }}</div>
</template>
<script setup>
const props = defineProps({
message: String
});
</script>注意事項(xiàng):
- 保持單向數(shù)據(jù)流,子組件不要直接修改 props。
- 可通過
defineProps設(shè)置類型校驗(yàn)和默認(rèn)值。
2. defineEmits 子傳父
適用場(chǎng)景:子組件向父組件傳遞數(shù)據(jù)
核心用法:defineEmits 定義自定義事件
<!-- 子組件 Child.vue -->
<template>
<button @click="sendData">發(fā)送數(shù)據(jù)</button>
</template>
<script setup>
const emit = defineEmits(['update']);
function sendData() {
emit('update', 'Data from Child');
}
</script>
<!-- 父組件 Parent.vue -->
<template>
<Child @update="handleUpdate" />
</template>
<script setup>
function handleUpdate(data) {
console.log('接收到子組件數(shù)據(jù):', data);
}
</script>補(bǔ)充:
- 推薦使用
update:propName命名規(guī)范(如update:count)。 - 避免直接傳遞父組件方法給子組件調(diào)用(如
<Child :onUpdate="handleUpdate" />)。
3. $attrs 屬性透?jìng)?/h3>
適用場(chǎng)景:透?jìng)魑绰暶鞯膶傩缘阶咏M件
核心用法:$attrs 自動(dòng)繼承父組件未聲明的屬性
<!-- 父組件 Parent.vue -->
<template>
<Child :customAttr="123" />
</template>
<!-- 子組件 Child.vue -->
<template>
<div v-attrs="$attrs"></div>
</template>
<script setup>
import { useAttrs } from 'vue';
const attrs = useAttrs();
console.log(attrs.customAttr); // 輸出 123
</script>4. ref + defineExpose
適用場(chǎng)景:父組件調(diào)用子組件方法或訪問子組件數(shù)據(jù)
核心用法:ref 獲取子組件實(shí)例,defineExpose 暴露方法/數(shù)據(jù)
<!-- 父組件 Parent.vue -->
<template>
<Child ref="childRef" />
<button @click="callChildMethod">調(diào)用子組件方法</button>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const childRef = ref(null);
function callChildMethod() {
childRef.value?.childMethod();
}
</script>
<!-- 子組件 Child.vue -->
<script setup>
function childMethod() {
console.log('子組件方法被調(diào)用');
}
defineExpose({ childMethod });
</script>注意事項(xiàng):
- 僅在必要時(shí)使用(如表單驗(yàn)證),避免過度依賴。
5. v-model 雙向綁定
適用場(chǎng)景:實(shí)現(xiàn)父子組件雙向數(shù)據(jù)綁定
核心用法:modelValue + update:modelValue
<!-- 父組件 Parent.vue -->
<template>
<Child v-model="value" />
</template>
<script setup>
import { ref } from 'vue';
const value = ref('初始值');
</script>
<!-- 子組件 Child.vue -->
<template>
<input :value="modelValue" @input="updateValue" />
</template>
<script setup>
const props = defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
function updateValue(e) {
emit('update:modelValue', e.target.value);
}
</script>二、兄弟組件通信
6. 父組件中轉(zhuǎn)
適用場(chǎng)景:兄弟組件通過父組件共享數(shù)據(jù)
<!-- 父組件 Parent.vue -->
<template>
<BrotherA @data-change="handleDataChange" />
<BrotherB :shared-data="sharedData" />
</template>
<script setup>
import { ref } from 'vue';
const sharedData = ref('');
function handleDataChange(data) {
sharedData.value = data;
}
</script>7. mitt 事件總線
適用場(chǎng)景:輕量級(jí)解耦通信(無共同父組件)
核心用法:mitt 創(chuàng)建事件中心
// eventBus.js
import mitt from 'mitt';
export const emitter = mitt();
// 組件A
<script setup>
import { emitter } from './eventBus.js';
function sendData() {
emitter.emit('brother-event', { id: 1 });
}
</script>
// 組件B
<script setup>
import { emitter } from './eventBus.js';
emitter.on('brother-event', (data) => {
console.log('接收到數(shù)據(jù):', data);
});
</script>8. 全局狀態(tài)管理(Pinia/Vuex)
適用場(chǎng)景:復(fù)雜應(yīng)用中的全局狀態(tài)共享
// store/counter.js (Pinia)
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: { increment() { this.count++; } }
});
// 組件A
<script setup>
import { useCounterStore } from '@/store/counter';
const store = useCounterStore();
store.increment();
</script>
// 組件B
<script setup>
import { useCounterStore } from '@/store/counter';
const store = useCounterStore();
console.log(store.count);
</script>三、跨層級(jí)通信
9. provide/inject
適用場(chǎng)景:祖孫組件或深層嵌套組件通信
<!-- 父組件 Parent.vue -->
<script setup>
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme);
</script>
<!-- 子組件 Child.vue -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
console.log('當(dāng)前主題:', theme.value);
</script>10. 全局狀態(tài)管理(Pinia/Vuex)
與兄弟組件通信中的 Pinia 用法一致,適用于跨層級(jí)狀態(tài)共享。
四、其他通信方式
11. 瀏覽器本地存儲(chǔ)(localStorage/sessionStorage)
適用場(chǎng)景:持久化數(shù)據(jù)共享(如用戶偏好設(shè)置)
// 存儲(chǔ)數(shù)據(jù)
localStorage.setItem('user', JSON.stringify({ name: '豆豆' }));
// 讀取數(shù)據(jù)
const user = JSON.parse(localStorage.getItem('user'));
console.log(user.name); // 輸出 豆豆12. 全局 window 對(duì)象
適用場(chǎng)景:臨時(shí)跨組件通信(慎用)
12. 全局 window 對(duì)象 適用場(chǎng)景:臨時(shí)跨組件通信(慎用)
13. ES6 模塊化(import/export)
適用場(chǎng)景:常量或工具函數(shù)共享
// constants.js
export const API_URL = 'https://api.example.com';
// 組件中使用
import { API_URL } from '@/constants';
console.log(API_URL); // 輸出 https://api.example.com14. 作用域插槽(Slot Props)
適用場(chǎng)景:父組件向子組件傳遞函數(shù)或配置對(duì)象
<!-- 父組件 Parent.vue -->
<template>
<Child>
<template #default="{ config }">
<div :style="config">{{ config.title }}</div>
</template>
</Child>
</template>
<!-- 子組件 Child.vue -->
<script setup>
import { reactive } from 'vue';
const config = reactive({ title: 'Slot Injected Config' });
</script>五、最佳實(shí)踐建議
優(yōu)先選擇標(biāo)準(zhǔn)化方案
80% 場(chǎng)景使用 props + emits。
復(fù)雜場(chǎng)景選擇 provide/inject 或狀態(tài)管理庫。
避免過度使用全局狀態(tài)
僅當(dāng)數(shù)據(jù)需要在多組件間共享時(shí)使用 Pinia/Vuex。
善用 $attrs
減少子組件 props 定義,實(shí)現(xiàn)屬性透?jìng)鳌?/p>
謹(jǐn)慎操作 ref
僅在必要時(shí)直接調(diào)用子組件方法,保持組件解耦。
事件命名規(guī)范
使用 on[EventName] 格式,如 on:update。
六、總結(jié)
Vue3 提供了豐富且靈活的組件通信方式,開發(fā)者應(yīng)根據(jù)具體場(chǎng)景選擇最優(yōu)方案。以下是常見場(chǎng)景的推薦選擇:
| 場(chǎng)景 | 推薦通信方式 |
|---|---|
| 父子通信 | props + defineEmits |
| 兄弟組件通信 | mitt 或父組件中轉(zhuǎn) |
| 跨層級(jí)通信 | provide/inject 或 Pinia |
| 全局狀態(tài)共享 | Pinia 或 Vuex |
| 臨時(shí)數(shù)據(jù)共享 | localStorage 或 window |
掌握這些通信方式后,可以更高效地構(gòu)建復(fù)雜應(yīng)用。建議將示例代碼復(fù)制到項(xiàng)目中運(yùn)行,觀察不同方式的數(shù)據(jù)流向和效果差異。
以上就是Vue3實(shí)現(xiàn)組件通信的14種方式詳解與實(shí)戰(zhàn)的詳細(xì)內(nèi)容,更多關(guān)于Vue3組件通信方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue雙向錨點(diǎn)實(shí)現(xiàn)過程簡(jiǎn)易版(scrollIntoView)
這篇文章主要介紹了vue雙向錨點(diǎn)實(shí)現(xiàn)過程簡(jiǎn)易版(scrollIntoView),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
vue cli 3.0通用打包配置代碼,不分一二級(jí)目錄
這篇文章主要介紹了vue cli 3.0通用打包配置代碼,不分一二級(jí)目錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
vue 請(qǐng)求后臺(tái)數(shù)據(jù)的實(shí)例代碼
本篇文章主要介紹了vue 請(qǐng)求后臺(tái)數(shù)據(jù)的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧、2017-06-06
Vue?Router4路由導(dǎo)航守衛(wèi)實(shí)例全面解析
這篇文章主要為大家介紹了Vue?Router4路由導(dǎo)航守衛(wèi)實(shí)例全面解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
vue?請(qǐng)求后端數(shù)據(jù)的示例代碼
在vue中,我們?nèi)绾瓮ㄟ^請(qǐng)求接口來訪問后端的數(shù)據(jù)呢?在這里簡(jiǎn)單總結(jié)了一個(gè)小示例,對(duì)vue請(qǐng)求后端數(shù)據(jù)實(shí)例代碼感興趣的朋友一起看看吧2022-09-09
Vue3實(shí)現(xiàn)Message消息組件示例
在大多數(shù) web 產(chǎn)品中,全局的 Message 組件占有較大的使用場(chǎng)景,本文主要介紹了Vue3實(shí)現(xiàn)Message消息組件示例,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06

