文章目錄
- 前言
- 一、父子組件通信
- 1.父組件向子組件通信
- 2.子組件向父組件通信
- 3.ref父組件直接操作子組件通信。
- 二、跨代通信
- 1. 跨層級通信
- 2.事件總線通信
- 總結
前言
vue3的組件通信和vue2相比在語法上會有些差距,且vue3有的通信方式也在功能上比vue2更加完善,比如provide/inject,vue3相比vue2多了支持響應式的功能。這里主要列出vue3的組件通信,且使用vue3的組合式API風格來實現。
提示:以下是本篇文章正文內容,下面案例可供參考
一、父子組件通信
1.父組件向子組件通信
(1)父組件傳遞:
只需要在引入的子組件標簽上,傳入(子組件那里已經定義的)參數名對應的值即可。
語法:
<template><子組件名稱 :參數名1="值" :參數名2="值"></子組件名稱></template>
(2)子組件接收:
使用props關鍵字。在vue2(選項式API)中,props直接定義在最外層和data、methods同級,而vue3的組合式api中則需要通過defineProps來定義,
即語法為:(語法糖形式)
const props = defineProps({ 參數名1: 參數類型, 參數名2: 參數類型 });
如果是setup()形式,則和setup()同級,寫法和選項式api一致,一般寫setup上面:
export default {props: {參數1: 參數值},setup(props) {// setup() 接收 props 作為第一個參數console.log(props.參數1)}
}
當然defineProps中不僅可以傳對象也可以傳字符串數組,一般是傳遞對象,因為需要定義參數類型。
使用時語法:props.參數名1
整體示例:
子組件:
ChildComponent.vue
<script setup>
import { ref } from 'vue';const props = defineProps({title: {type: String,default: '默認標題',},btnFun: {type: Function,default: () => {},},
});
const inputValue = ref('');
</script><template><div><h2>{{ props.title }}</h2><a-button type="primary" @click="props.btnFun">完成</a-button><a-input v-model:value="inputValue" placeholder="請輸入" /></div>
</template>
父組件:
<template><child-component :title="測試標題" :btn-fun="() => { console.log('按鈕被點擊'); }"></child-component>
</template>
其中ChildComponent和btnFun可以是原值,也可以是“-”分割后的值,都可以識別。
2.子組件向父組件通信
使用emit,vue3定義emit,使用defineEmits,
子組件里:
定義語法:
const emit = defineEmits(['child-event1','child-event2']);
setup()形式定義位置同1中的defineProps。
觸發語法:
emit('child-event1',要傳遞的參數)
父組件里:
接收語法:
<子組件名 @child-event1='本地定義函數名'/>
整體例子:
<!-- 父組件 -->
<template><ChildComponent :message="parentMsg" @child-event="handleEvent" />
</template><script setup>
import { ref } from 'vue';
const parentMsg = ref('來自父組件的數據');const handleEvent = (payload) => {console.log('子組件傳來:', payload);
};
</script><!-- 子組件:ChildComponent -->
<template><button @click="$emit('child-event', '觸發事件')">發送數據</button>
</template><script setup>
const props = defineProps({message: String
});
const emit = defineEmits(['child-event']);
</script>
3.ref父組件直接操作子組件通信。
vue3中的語法,父組件:
<template><子組件名稱 ref="ref名稱"/>
</template><script setup>
import { ref } from 'vue';
const 'ref名稱' = ref(null); // 父組件可以通過'ref名稱'拿到子組件上的方法和data等數據</script>
示例:
<!-- 父組件 -->
<template><ChildComponent ref="childRef" />
</template><script setup>
import { ref, onMounted } from 'vue';
const childRef = ref(null);onMounted(() => {childRef.value.someMethod(); // 調用子組件方法
});
</script>
進階:如果是遇到多個子組件按需加載的情況,則此時若要通過ref獲取到子組件的信息,則子組件還需加上 defineExpose
。
場景:
is里面循環的子組件(StepOne、StepTwo)里需要加上:
二、跨代通信
1. 跨層級通信
使用provide/inject函數, 其中provide為后代組件提供數據,需要接收的后代組件則是通過inject去接收數據。
語法:
祖先組件發送數據:provide('注入名', 要傳遞的參數);
后代接收數據:inject('注入名',要接收的參數);
使用示例:
<!-- 祖先組件 -->
<script setup>
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme); // 提供數據
</script><!-- 深層子組件 -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme'); // 注入數據
console.log(theme.value); // 'dark'
</script>
另:如果沒有使用setup語法糖,provide(/inject)要在setup()函數內調用:
import { provide } from 'vue'export default {setup() {provide(/* 注入名 */ 'message', /* 值 */ 'hello!')}
}
進階:
provide第二個參數,即要傳遞的參數值可以是任意類型,包括響應式的狀態,比如一個 ref;
provide可以傳遞多個,后代按照注入名字接收,如果有重復的則以離得最近的父代為準。
import { ref, provide } from 'vue'const count = ref(0);
function updateCount() {count ++;
}
provide('key', { count, updateCount });
后代接收時:
<script setup>
import { inject } from 'vue'const { count, updateCount } = inject('location');
</script><template><button @click="updateCount">{{ count }}</button>
</template>
2.事件總線通信
使用mitt工具:
下載:npm install mitt
創建事件總線模塊:
event-bus.js
import mitt from 'mitt';const emitter = mitt();export default emitter;
發送事件組件:
SenderComponent.vue
<template><button @click="sendMessage">發送消息</button>
</template><script setup>
import emitter from './event-bus';const sendMessage = () => {emitter.emit('custom-event', {message: '來自SenderComponent的消息',timestamp: new Date().toISOString()});
};
</script>
接收事件組件:
ReceiverComponent.vue
<template><div><p>接收到的消息: {{ receivedMessage }}</p></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import emitter from './event-bus';const receivedMessage = ref('等待消息...');const handleEvent = (payload) => {receivedMessage.value = payload.message;console.log('接收到事件:', payload);
};onMounted(() => {// 注冊事件監聽emitter.on('custom-event', handleEvent);
});onUnmounted(() => {// 移除事件監聽,防止內存泄漏emitter.off('custom-event', handleEvent);
});
</script>
總結
以上用了大概五種方式來闡述組件之間的通信,這些在日常開發中比較常見,對于vue入門來說是需要去掌握并靈活運用的,對于子父組件一開始會有混亂不清的情況,這種在以后的練習和熟悉中會逐漸分清。