在 Vue 3 中,eventBus 的概念已经被弱,不推荐使用全局事件总线
,
你需要一个轻量级的事件总线,可以自己封装一个 EventBus 类,也有一些替代方案
1、使用第三方库(如 mitt 或 tiny-emitter)
mitt 是一个轻量级的事件发射器,适合在 Vue 3 中替代事件总线。它不依赖 Vue 实例,体积小且易于使用。
javascript">npm install mitt
javascript">// src/utils/eventBus.js
import mitt from 'mitt';export const emitter = mitt();
javascript">import { emitter } from './utils/eventBus';
// 触发事件
emitter.emit('event-name', data);
// 取消监听
emitter.off('event-name', handler);
2、依赖注入
provide 和 inject 是 Vue 3 推荐的父子组件通信方式,适合在组件树中传递数据。
javascript">// 父组件
import { provide } from 'vue';
export default {setup() {provide('message', 'Hello from Parent');}
};
javascript">// 子组件
import { inject } from 'vue';
export default {setup() {const message = inject('message');console.log(message);}
};
3、使用vuex或者pina
对于复杂的状态管理,推荐使用 Vuex 或 Pinia。它们提供了更强大的状态管理能力,适合大型项目。
javascript">// store.js
import { createStore } from 'vuex';
export default createStore({state: {message: 'Hello from Vuex'},mutations: {updateMessage(state, payload) {state.message = payload;}}
});
javascript">import { useStore } from 'vuex';
export default {setup() {const store = useStore();store.commit('updateMessage', 'New Message');console.log(store.state.message);}
};
4、使用props和emits
对于父子组件通信,props 和 emits 是最直接的方式。
javascript"><template><ChildComponent :message="message" @update="handleUpdate" />
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},data() {return {message: 'Hello from Parent'};},methods: {handleUpdate(newMessage) {this.message = newMessage;}}
};
</script>
javascript"><template><button @click="updateMessage">Update Message</button>
</template><script>
export default {props: ['message'],emits: ['update'],methods: {updateMessage() {this.$emit('update', 'New Message');}}
};
</script>
5、自己封装
在 Vue 3 中,你可以通过创建一个 Vue 实例作为事件总线来实现类似的功能。
javascript">// src/eventBus.js
import { createApp } from 'vue';const eventBus = createApp({});// 添加自定义事件方法
eventBus.config.globalProperties.$emit = function (event, ...args) {this._eventBus.emit(event, ...args);
};eventBus.config.globalProperties.$on = function (event, callback) {this._eventBus.on(event, callback);
};eventBus.config.globalProperties.$off = function (event, callback) {this._eventBus.off(event, callback);
};// 创建一个内部的事件总线
eventBus._eventBus = {events: {},on(event, callback) {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(callback);},emit(event, ...args) {if (this.events[event]) {this.events[event].forEach(callback => {callback(...args);});}},off(event, callback) {if (this.events[event]) {this.events[event] = this.events[event].filter(cb => cb !== callback);}}
};export default eventBus;
子组件
javascript">// src/eventBus.js
import { createApp } from 'vue';const eventBus = createApp({});// 添加自定义事件方法
eventBus.config.globalProperties.$emit = function (event, ...args) {this._eventBus.emit(event, ...args);
};eventBus.config.globalProperties.$on = function (event, callback) {this._eventBus.on(event, callback);
};eventBus.config.globalProperties.$off = function (event, callback) {this._eventBus.off(event, callback);
};// 创建一个内部的事件总线
eventBus._eventBus = {events: {},on(event, callback) {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(callback);},emit(event, ...args) {if (this.events[event]) {this.events[event].forEach(callback => {callback(...args);});}},off(event, callback) {if (this.events[event]) {this.events[event] = this.events[event].filter(cb => cb !== callback);}}
};export default eventBus;
父组件:
javascript"><template><ChildComponent />
</template><script>
import ChildComponent from './ChildComponent.vue';
import eventBus from '../eventBus';export default {components: {ChildComponent},created() {// 监听事件eventBus.$on('custom-event', this.handleCustomEvent);},beforeUnmount() {// 组件销毁时移除事件监听eventBus.$off('custom-event', this.handleCustomEvent);},methods: {handleCustomEvent(message) {console.log('Event received:', message);// 在这里处理逻辑}}
}
</script>
使用类方法封装一个事件总线
javascript">// src/utils/EventBus.jsclass EventBus {constructor() {this.events = {};}/*** 监听事件* @param {string} event - 事件名称* @param {Function} callback - 回调函数*/$on(event, callback) {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(callback);}/*** 触发事件* @param {string} event - 事件名称* @param {...any} args - 传递给回调函数的参数*/$emit(event, ...args) {if (this.events[event]) {this.events[event].forEach(callback => {callback(...args);});}}/*** 移除事件监听* @param {string} event - 事件名称* @param {Function} callback - 回调函数*/$off(event, callback) {if (this.events[event]) {this.events[event] = this.events[event].filter(cb => cb !== callback);}}/*** 一次性监听事件* @param {string} event - 事件名称* @param {Function} callback - 回调函数*/$once(event, callback) {const onceCallback = (...args) => {callback(...args);this.$off(event, onceCallback);};this.$on(event, onceCallback);}
}// 创建一个 EventBus 实例
const eventBus = new EventBus();export default eventBus;
子组件
javascript"><template><button @click="handleClick">点击我</button>
</template><script>
import eventBus from '../utils/EventBus';export default {methods: {handleClick() {// 触发事件eventBus.$emit('custom-event', 'Hello from Child');}}
}
</script>
父组件
javascript"><template><ChildComponent />
</template><script>
import ChildComponent from './ChildComponent.vue';
import eventBus from '../utils/EventBus';export default {components: {ChildComponent},created() {// 监听事件eventBus.$on('custom-event', this.handleCustomEvent);},beforeUnmount() {// 组件销毁时移除事件监听eventBus.$off('custom-event', this.handleCustomEvent);},methods: {handleCustomEvent(message) {console.log('Event received:', message);// 在这里处理逻辑}}
}
</script>