vue3 跨组件方法调用。Vue 3 的 Provide / Inject 与 mitt 电脑版发表于:2024/9/15 22:37 mitt 是一个轻量级的事件发射器(event emitter),它可以很容易地集成到 Vue 3 应用中。 下面是一个使用 Vue 3 的 provide/inject 和 mitt 来实现跨组件事件通信的简单示例: ### 安装 mitt 首先,你需要在你的项目中安装 mitt。如果你使用的是 npm 或 yarn,可以通过以下命令来安装: ``` npm install mitt --save # 或者 yarn add mitt ``` ### 创建一个事件总线 在你的项目中,你可以创建一个单独的文件来管理 mitt 实例,这个实例将作为事件总线。 eventBus.js ``` import mitt from 'mitt'; export const eventBus = mitt(); ``` ### 在 Vue 应用中提供事件总线 然后,在你的 Vue 应用或某个祖先组件中,你可以使用 provide 来提供这个事件总线实例。 main.js 或某个祖先组件 ``` import { createApp } from 'vue'; import App from './App.vue'; import { eventBus } from './eventBus'; const app = createApp(App); // 在整个应用中提供 eventBus app.provide('eventBus', eventBus); app.mount('#app'); ``` 注意:在 Vue 3 中,provide 通常是在 setup 函数中使用的,但如果你想在整个应用范围内提供某些东西,可以像上面这样在创建应用实例时调用 app.provide。 ### 在组件中注入并使用事件总线 现在,你可以在任何子组件中通过 inject 来注入并使用这个事件总线了。 #### ComponentA.vue ``` <template> <button @click="emitEvent">Emit Event</button> </template> <script setup> import { inject } from 'vue'; // import { eventBus } from './eventBus'; // 注意:通常不需要直接导入,因为已经通过 provide 提供了。可以直接通过inject 获取 eventBus // 通过 inject 获取 eventBus const eventBus = inject('eventBus'); // 定义一个方法来触发事件 function emitEvent() { if (eventBus) { eventBus.emit('my-event', { message: 'Hello from Component A!' }); } } </script> ``` #### ComponentB.vue ``` <template> <div> <p>Received message: {{ message }}</p> </div> </template> <script setup> import { inject, ref, onUnmounted } from 'vue'; // 通过 inject 获取 eventBus const eventBus = inject('eventBus'); // 创建一个响应式引用来存储接收到的消息 const message = ref(''); // 监听 my-event 事件 if (eventBus) { eventBus.on('my-event', (data) => { message.value = data.message; }); // 在组件卸载时移除监听器,防止内存泄漏 onUnmounted(() => { eventBus.off('my-event'); }); } </script> ``` #### 注意事项 - 确保你的 eventBus 已经在 Vue 应用的根级别(如 main.js 或 main.ts)通过 app.provide 被提供。 - 在任何子组件中,你都可以通过 inject 来获取并使用这个 eventBus。 - 当你不再需要监听某个事件时(例如在组件卸载时),应该使用 eventBus.off 来移除监听器,以防止内存泄漏。这在 ComponentB.vue 的示例中已经展示过了。 - 如果你发现 inject 返回的是 undefined,那么可能是因为 provide 没有在组件的祖先链中被正确调用,或者 provide 和 inject 的键名不匹配。 666