vue3組件傳參的N種方法總結(jié)大全
一、父子組件傳參
父子組件是最常見的關(guān)系,傳參方式直接且高效。
1. Props(父?jìng)髯樱?/h3>
- 原理:父組件通過屬性綁定傳遞數(shù)據(jù),子組件通過
defineProps接收并使用。 - 示例:
- 父組件(Parent.vue):
vue
<template>
<Child :message="parentMsg" :user="userInfo" />
</template>
<script setup>
import Child from './Child.vue';
const parentMsg = 'Hello from Parent';
const userInfo = { name: 'Alice', age: 20 };
</script>
- 子組件(Child.vue):
vue
<template>
<p>{{ message }}</p>
<p>{{ user.name }}</p>
</template>
<script setup>
// 接收參數(shù)并指定類型(可選)
const props = defineProps({
message: String,
user: {
type: Object,
required: true
}
});
// 使用:props.message 或直接在模板中使用
</script>
- 特點(diǎn):?jiǎn)蜗驍?shù)據(jù)流(子組件不能直接修改 props,需通過事件通知父組件修改)。
defineProps接收并使用。- 父組件(Parent.vue):
vue
<template> <Child :message="parentMsg" :user="userInfo" /> </template> <script setup> import Child from './Child.vue'; const parentMsg = 'Hello from Parent'; const userInfo = { name: 'Alice', age: 20 }; </script> - 子組件(Child.vue):
vue
<template> <p>{{ message }}</p> <p>{{ user.name }}</p> </template> <script setup> // 接收參數(shù)并指定類型(可選) const props = defineProps({ message: String, user: { type: Object, required: true } }); // 使用:props.message 或直接在模板中使用 </script>
2. Emits(子傳父)
- 原理:子組件通過
emit觸發(fā)事件并傳遞數(shù)據(jù),父組件監(jiān)聽事件接收數(shù)據(jù)。 - 示例:
- 子組件(Child.vue):
vue
<template> <button @click="handleClick">Send Data</button> </template> <script setup> // 聲明觸發(fā)的事件(可選,增強(qiáng)類型校驗(yàn)) const emit = defineEmits(['sendData', 'update']); const handleClick = () => { emit('sendData', 'Data from Child'); // 傳遞單個(gè)值 emit('update', { id: 1, status: 'done' }); // 傳遞對(duì)象 }; </script> - 父組件(Parent.vue):
vue
<template> <Child @sendData="onReceive" @update="onUpdate" /> </template> <script setup> const onReceive = (data) => { console.log('Received:', data); // 輸出:Data from Child }; const onUpdate = (obj) => { console.log('Updated:', obj); // 輸出:{ id: 1, status: 'done' } }; </script>
- 子組件(Child.vue):
- 特點(diǎn):適用于子組件向父組件傳遞交互結(jié)果(如表單提交、狀態(tài)變更)。
3. v-model(雙向綁定)
- 原理:語法糖,結(jié)合
props和emits實(shí)現(xiàn)父子組件數(shù)據(jù)雙向同步。 - 示例:
- 子組件(Child.vue):
vue
<template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template> <script setup> defineProps(['modelValue']); defineEmits(['update:modelValue']); </script> - 父組件(Parent.vue):
vue
<template> <Child v-model="inputValue" /> <p>Parent Value: {{ inputValue }}</p> </template> <script setup> import { ref } from 'vue'; const inputValue = ref(''); </script>
- 子組件(Child.vue):
- 擴(kuò)展:支持多個(gè) v-model(如
v-model:name、v-model:age),需對(duì)應(yīng)props和emits。
4. refs(父訪問子組件數(shù)據(jù) / 方法)
- 原理:父組件通過
ref獲取子組件實(shí)例,直接訪問子組件的屬性或方法。 - 示例:
- 子組件(Child.vue):
vue
<script setup> import { ref } from 'vue'; const count = ref(0); const increment = () => count.value++; // 暴露給父組件的屬性/方法(setup語法糖需顯式暴露) defineExpose({ count, increment }); </script> - 父組件(Parent.vue):
vue
<template> <Child ref="childRef" /> <button @click="accessChild">訪問子組件</button> </template> <script setup> import { ref } from 'vue'; import Child from './Child.vue'; const childRef = ref(null); const accessChild = () => { console.log(childRef.value.count); // 訪問屬性 childRef.value.increment(); // 調(diào)用方法 }; </script>
- 子組件(Child.vue):
- 注意:避免過度依賴,優(yōu)先通過 props/emits 通信,減少耦合。
二、祖孫 / 跨級(jí)組件傳參
當(dāng)組件層級(jí)較深(如祖父→父→子),使用provide/inject更簡(jiǎn)潔。
5. Provide/Inject(依賴注入)
- 原理:祖先組件通過
provide提供數(shù)據(jù),后代組件通過inject注入并使用,無視層級(jí)。 - 示例:
- 祖先組件(Grandpa.vue):
vue
<script setup> import { provide, ref } from 'vue'; const theme = ref('light'); // 提供靜態(tài)數(shù)據(jù)或響應(yīng)式數(shù)據(jù) provide('theme', theme); provide('user', { name: 'Bob' }); </script> - 后代組件(Grandchild.vue):
vue
<script setup> import { inject, watch } from 'vue'; // 注入數(shù)據(jù)(可指定默認(rèn)值) const theme = inject('theme', ref('dark')); const user = inject('user'); // 響應(yīng)式數(shù)據(jù)可直接使用或監(jiān)聽 watch(theme, (newVal) => { console.log('Theme changed:', newVal); }); </script>
- 祖先組件(Grandpa.vue):
- 特點(diǎn):適用于跨多級(jí)傳參,但數(shù)據(jù)追蹤較難,建議配合 TypeScript 類型定義使用。
- 注意:若需修改注入的數(shù)據(jù),建議在祖先組件中提供修改方法(如
provide('setTheme', (val) => theme.value = val)),避免后代直接修改。
三、兄弟 / 任意組件傳參
非父子 / 跨級(jí)的組件(如兄弟組件、不相關(guān)組件),可通過全局狀態(tài)管理或事件總線實(shí)現(xiàn)。
6. Pinia/Vuex(全局狀態(tài)管理)
- 原理:通過全局存儲(chǔ)管理數(shù)據(jù),任何組件都可讀取或修改,適用于大型應(yīng)用。
- 示例(Pinia):
- 定義 Store(stores/counter.js):
javascript
import { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), actions: { increment() { this.count++; } } }); - 組件 A(使用并修改):
vue
<script setup> import { useCounterStore } from './stores/counter'; const store = useCounterStore(); store.increment(); // 調(diào)用方法修改狀態(tài) </script> - 組件 B(讀?。?p>vue
<template> <p>Global Count: {{ store.count }}</p> </template> <script setup> import { useCounterStore } from './stores/counter'; const store = useCounterStore(); </script>
- 定義 Store(stores/counter.js):
- 特點(diǎn):適合共享復(fù)雜狀態(tài)(如用戶信息、購物車),支持響應(yīng)式和開發(fā)者工具調(diào)試。
7. 事件總線(mitt)
- 原理:通過全局事件中心,組件可觸發(fā)事件或監(jiān)聽事件,實(shí)現(xiàn)解耦通信。
- 步驟:
安裝 mitt:
創(chuàng)建事件總線(bus.js):npm install mittjavascript
組件 A(觸發(fā)事件):import mitt from 'mitt'; export const bus = mitt();
vue
組件 B(監(jiān)聽事件):<script setup> import { bus } from './bus'; const sendData = () => { bus.emit('msg', 'Hello from A'); // 觸發(fā)事件并傳參 }; </script>vue
<script setup> import { bus, onUnmounted } from 'vue'; onMounted(() => { // 監(jiān)聽事件 bus.on('msg', (data) => { console.log('Received from A:', data); }); }); // 組件卸載時(shí)移除監(jiān)聽,避免內(nèi)存泄漏 onUnmounted(() => { bus.off('msg'); }); </script> - 特點(diǎn):輕量靈活,適合小型應(yīng)用或簡(jiǎn)單場(chǎng)景,大型應(yīng)用建議用 Pinia。
8. URL 參數(shù)(路由傳參)
- 原理:通過路由的 query 或 params 傳遞數(shù)據(jù),適用于頁面級(jí)組件跳轉(zhuǎn)。
- 示例(Vue Router):
- 跳轉(zhuǎn)時(shí)傳參:
vue
<template> <!-- query參數(shù)(顯式在URL,如?name=Alice) --> <router-link :to="{ path: '/detail', query: { id: 1 } }">詳情頁</router-link> <!-- params參數(shù)(需在路由配置中定義,如/detail/1) --> <router-link :to="{ name: 'Detail', params: { id: 1 } }">詳情頁</router-link> </template> - 接收參數(shù):
vue
<script setup> import { useRoute } from 'vue-router'; const route = useRoute(); console.log(route.query.id); // query參數(shù) console.log(route.params.id); // params參數(shù) </script>
- 跳轉(zhuǎn)時(shí)傳參:
- 特點(diǎn):數(shù)據(jù)可通過 URL 共享,刷新頁面不丟失(query),但適合傳遞簡(jiǎn)單數(shù)據(jù)(如 ID、篩選條件)。
四、其他特殊方式
9. 插槽(Slots)傳參
- 原理:父組件通過插槽向子組件傳遞內(nèi)容(含數(shù)據(jù)),子組件通過
slot-scope接收。 - 示例:
- 子組件(Child.vue):
vue
<template> <div> <!-- 向插槽傳遞數(shù)據(jù) --> <slot :item="user" :count="10"></slot> </div> </template> <script setup> const user = { name: 'Charlie' }; </script> - 父組件(Parent.vue):
vue
<template> <Child> <!-- 接收插槽傳遞的數(shù)據(jù) --> <template #default="slotProps"> <p>{{ slotProps.item.name }}</p> <p>{{ slotProps.count }}</p> </template> </Child> </template>
- 子組件(Child.vue):
- 特點(diǎn):適合傳遞帶結(jié)構(gòu)的內(nèi)容,結(jié)合數(shù)據(jù)動(dòng)態(tài)渲染。
總結(jié)與選擇建議
| 傳參方式 | 適用場(chǎng)景 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|
| Props/Emits | 父子組件 | 簡(jiǎn)單直接,單向數(shù)據(jù)流清晰 | 層級(jí)深時(shí)繁瑣 |
| v-model | 父子組件雙向綁定 | 語法簡(jiǎn)潔 | 僅適用于單個(gè)值雙向同步 |
| refs | 父訪問子組件方法 / 屬性 | 直接高效 | 耦合度高,破壞封裝 |
| Provide/Inject | 跨多級(jí)組件 | 無視層級(jí) | 數(shù)據(jù)追蹤難,不適合頻繁修改 |
| Pinia/Vuex | 全局 / 復(fù)雜狀態(tài) | 統(tǒng)一管理,響應(yīng)式 | 配置稍復(fù)雜 |
| 事件總線 | 兄弟 / 簡(jiǎn)單跨組件 | 輕量靈活 | 大型應(yīng)用易混亂 |
| URL 參數(shù) | 路由跳轉(zhuǎn)的頁面級(jí)組件 | 刷新不丟失 | 適合簡(jiǎn)單數(shù)據(jù) |
| 插槽傳參 | 帶結(jié)構(gòu)的內(nèi)容傳遞 | 結(jié)合數(shù)據(jù)與 UI | 僅用于插槽內(nèi)容 |
根據(jù)場(chǎng)景選擇:
- 父子組件優(yōu)先用Props/Emits或v-model;
- 跨多級(jí)用Provide/Inject;
- 全局共享用Pinia;
- 簡(jiǎn)單跨組件用事件總線;
- 頁面跳轉(zhuǎn)用路由參數(shù)。
到此這篇關(guān)于vue3組件傳參的N種方法的文章就介紹到這了,更多相關(guān)vue3組件傳參內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue2.6.10+vite2開啟template模板動(dòng)態(tài)編譯的過程
這篇文章主要介紹了vue2.6.10+vite2開啟template模板動(dòng)態(tài)編譯,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02
vue+relation-graph繪制關(guān)系圖實(shí)用組件操作方法
這篇文章主要介紹了vue+relation-graph繪制關(guān)系圖實(shí)用組件操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
Vue 解決多級(jí)動(dòng)態(tài)面包屑導(dǎo)航的問題
今天小編就為大家分享一篇Vue 解決多級(jí)動(dòng)態(tài)面包屑導(dǎo)航的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11
淺析vue 函數(shù)配置項(xiàng)watch及函數(shù) $watch 源碼分享
這篇文章主要介紹了vue 函數(shù)配置項(xiàng)watch及函數(shù) $watch 源碼分享 ,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11
在vue3項(xiàng)目中實(shí)現(xiàn)國際化的代碼示例
國際化就是指在一個(gè)項(xiàng)目中,項(xiàng)目中的語言可以進(jìn)行切換(中英文切換),那么在實(shí)際項(xiàng)目中是如何實(shí)現(xiàn)的呢,本文就給大家詳細(xì)的介紹實(shí)現(xiàn)方法,需要的朋友可以參考下2023-07-07
關(guān)于vue 結(jié)合原生js 解決echarts resize問題
這篇文章主要介紹了關(guān)于vue 結(jié)合原生js 解決echarts resize問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07

