Vu3 跨组件通讯
通过父组件传递
这是最常见的跨组件通信方式之一,适用于兄弟组件或跨级组件之间的通信。通过父组件作为中介来传递数据。
示例
- 父组件(ParentComponent.vue):
1<template>
2 <div>
3 <child-a @send-message="handleMessage" />
4 <child-b :message="message" />
5 <p>{{ message }}</p>
6 </div>
7</template>
8
9<script setup>
10import { ref } from 'vue';
11import ChildA from './ChildA.vue';
12import ChildB from './ChildB.vue';
13
14const message = ref('');
15
16const handleMessage = (data) => {
17 message.value = data;
18};
19</script>
- 子组件 A(ChildA.vue):
1<template>
2 <button @click="sendMessage">发送消息</button>
3</template>
4
5<script setup>
6const emit = defineEmits(['send-message']);
7
8const sendMessage = () => {
9 emit('send-message', '这是来自 ChildA 的消息');
10};
11</script>
- 子组件 B(ChildB.vue):
深色版本
1<template>
2 <p>{{ message }}</p>
3</template>
4
5<script setup>defineProps({
7 message: String
8});
9</script>
2. 使用 Composition API 和 Refs
Vue 3 引入了 Composition API,使得跨组件通信更加灵活。
示例
- 父组件(ParentComponent.vue):
1<template>
2 <div>
3 <child-a @send-message="handleMessage" />
4 <child-b :message="message" />
5 <p>{{ message }}</p>
6 </div>
7</template>
8
9<script setup>
10import { ref } from 'vue';
11import ChildA from './ChildA.vue';
12import ChildB from './ChildB.vue';
13
14const message = ref('');
15
16const handleMessage = (data) => {
17 message.value = data;
18};
19</script>
- 子组件 A(ChildA.vue):
1<template>
2 <button @click="sendMessage">发送消息</button>
3</template>
4
5<script setup>
6const emit = defineEmits(['send-message']);
7
8const sendMessage = () => {
9 emit('send-message', '这是来自 ChildA 的消息');
10};
11</script>
- 子组件 B(ChildB.vue):
1<template>
2 <p>{{ message }}</p>
3</template>
4
5<script setup>
6defineProps({
7 message: String
8});
9</script>
3. 使用 Vuex
Vuex 是 Vue.js 的官方状态管理库,适合管理全局状态,适用于大型应用或需要多个组件共享状态的情况。
示例
- 安装 Vuex:
1npm install vuex --save
- 创建 Vuex store:
1import { createPinia } from 'pinia';
2import { defineStore } from 'pinia';
3
4const pinia = createPinia();
5
6const useMainStore = defineStore('main', {
7 state: () => ({
8 message: ''
9 }),
10 actions: {
11 setMessage(message) {
12 this.message = message;
13 }
14 },
15 getters: {
16 getMessage: (state) => state.message
17 }
18});
19
20export { pinia, useMainStore };
- 主入口文件(main.js 或 main.ts):
1import { createApp } from 'vue';
2import App from './App.vue';
3import { pinia } from './store';
4
5const app = createApp(App);
6app.use(pinia);
7app.mount('#app');
- 组件中使用 Vuex:
1<template>
2 <div>
3 <p>{{ message }}</p>
4 <button @click="sendMessage">发送消息</button>
5 </div>
6</template>
7
8<script setup>
9import { useMainStore } from './store';
10
11const store = useMainStore();
12
13const sendMessage = () => {
14 store.setMessage('这是来自组件的消息');
15};
16</script>
4. 使用事件总线(Event Bus)
事件总线是一种轻量级的跨组件通信方式,适用于需要跨组件通信但又不想引入 Vuex 的场景。
示例
- 创建事件总线:
1import { createApp } from 'vue';
2
3const app = createApp({});
4export const EventBus = app.config.globalProperties;
- 子组件 A(ChildA.vue):
1<template>
2 <button @click="sendMessage">发送消息</button>
3</template>
4
5<script setup>
6import { EventBus } from '../eventBus';
7
8const sendMessage = () => {
9 EventBus.$emit('message-event', '这是来自 ChildA 的消息');
10};
11</script>
- 子组件 B(ChildB.vue):
1<template>
2 <p>{{ message }}</p>
3</template>
4
5<script setup>
6import { EventBus } from '../eventBus';
7
8const message = ref('');
9
10watchEffect(() => {
11 EventBus.$on('message-event', (data) => {
12 message.value = data;
13 });
14
15 onBeforeUnmount(() => {
16 EventBus.$off('message-event', (data) => {
17 message.value = data;
18 });
19 });
20});
21</script>
5. 使用全局事件监听器
通过将事件监听器挂载到 Vue.prototype
上来实现全局事件监听。在 Vue 3 中,可以使用全局的 app.config.globalProperties
。
示例
- 主入口文件(main.js 或 main.ts):
1import { createApp } from 'vue';
2import App from './App.vue';
3
4const app = createApp(App);
5
6app.config.globalProperties.$eventBus = new EventTarget();
7
8app.mount('#app');
- 子组件 A(ChildA.vue):
1<template>
2 <button @click="sendMessage">发送消息</button>
3</template>
4
5<script setup>
6import { onMounted, onUnmounted } from 'vue';
7import { $eventBus } from '../main';
8
9const sendMessage = () => {
10 $eventBus.dispatchEvent(new CustomEvent('message-event', { detail: '这是来自 ChildA 的消息' }));
11};
12
13onMounted(() => {
14 $eventBus.addEventListener('message-event', (event) => {
15 console.log(event.detail);
16 });
17});
18
19onUnmounted(() => {
20 $eventBus.removeEventListener('message-event', (event) => {
21 console.log(event.detail);
22 });
23});
24</script>
- 子组件 B(ChildB.vue):
1<template>
2 <p>{{ message }}</p>
3</template>
4
5<script setup>
6import { ref, onMounted, onUnmounted } from 'vue';
7import { $eventBus } from '../main';
8
9const message = ref('');
10
11onMounted(() => {
12 $eventBus.addEventListener('message-event', (event) => {
13 message.value = event.detail;
14 });
15});
16
17onUnmounted(() => {
18 $eventBus.removeEventListener('message-event', (event) => {
19 message.value = event.detail;
20 });
21});
22</script>
总结
以上是 Vue 3 中几种常见的跨组件通信方式。选择哪种方式取决于你的具体需求:
- 通过父组件传递:适用于兄弟组件或跨级组件之间的简单通信。
- 使用 Composition API 和 Refs:利用 Vue 3 的新特性进行灵活的数据管理和通信。
- 使用 Vuex:适用于需要全局状态管理的应用,适合大型应用或多个组件共享状态的场景。
- 使用事件总线(Event Bus):适用于轻量级的跨组件通信,不需要引入 Vuex 的场景。
- 使用全局事件监听器:通过全局的
app.config.globalProperties
挂载事件监听器,适用于简单场景。