概述
在 Vue 3 中,组件间通信主要有以下几种方式:
父子组件通信
兄弟组件通信
非直接关系组件通信(比如通过 EventBus 或 Vuex)
父子组件通信
Props
<!-- Parent.vue -->
<template>
<div>
<h1>父组件</h1>
<Child :message="parentMessage" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const parentMessage = ref('Hello from Parent!');
</script>
<!-- Child.vue -->
<template>
<div>
<h2>子组件</h2>
<p>{{ message }}</p>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
message: String
});
</script>
Parent.vue 组件通过 props 将信息传递给 Child.vue 组件,子组件简单地接收并展示了这个信息
Emits 子组件需要向父组件发送消息,可以使用 $emit 事件
<!-- Child.vue -->
<template>
<div>
<h2>子组件</h2>
<button @click="sendMessage">发送消息</button>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps();
const emit = defineEmits();
function sendMessage() {
emit('childMessage', 'Hello from Child!');
}
</script>
<!-- Parent.vue -->
<template>
<div>
<h1>父组件</h1>
<Child @childMessage="handleChildMessage" />
<p>接收到的消息: {{ childMessage }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const childMessage = ref('');
function handleChildMessage(message) {
childMessage.value = message;
}
</script>
Child.vue 组件通过 emit 事件向父组件发送数据,而父组件使用 @childMessage 监听该事件并处理接收到的消息
兄弟组件通信
借助父组件或者更现代的状态管理工具
使用父组件作为桥梁
在父组件中定义一个共享的状态,然后通过 props 将状态传递给两个兄弟组件:
<!-- Parent.vue -->
<template>
<div>
<BrotherA @updateSiblingData="updateData" />
<BrotherB :siblingData="siblingData" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import BrotherA from './BrotherA.vue';
import BrotherB from './BrotherB.vue';
const siblingData = ref('');
function updateData(newData) {
siblingData.value = newData;
}
</script>
<!-- BrotherA.vue -->
<template>
<div>
<h2>兄弟组件 A</h2>
<button @click="sendData">发送数据到兄弟 B</button>
</div>
</template>
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits();
function sendData() {
emit('updateSiblingData', 'Data from Brother A');
}
</script>
<!-- BrotherB.vue -->
<template>
<div>
<h2>兄弟组件 B</h2>
<p>来自兄弟 A 的数据: {{ siblingData }}</p>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
siblingData: String
});
</script>
BrotherA.vue 组件通过事件更新父组件中的 siblingData,而 BrotherB.vue 则通过 props 接收这个数据。
非直接关系组件通信
EventBus
import { reactive } from 'vue';
const EventBus = reactive({
events: {},
emit(event, data) {
this.events[event] && this.events[event].forEach(callback => callback(data));
},
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
});
export default EventBus;
<!-- ComponentA.vue -->
<template>
<button @click="sendEvent">发送事件</button>
</template>
<script setup>
import EventBus from './eventBus';
function sendEvent() {
EventBus.emit('event-from-a', 'Hello from Component A!');
}
</script>
<!-- ComponentB.vue -->
<template>
<div>{{ receivedData }}</div>
</template>
<script setup>
import EventBus from './eventBus';
import { ref, onMounted } from 'vue';
const receivedData = ref('');
onMounted(() => {
EventBus.on('event-from-a', (data) => {
receivedData.value = data;
});
});
</script>
ComponentA.vue 组件可以通过 emit 事件发送消息,而 ComponentB.vue 组件可以通过 on 监听相应的事件