一、什么是事件总线
事件总线(Event Bus)是一种组件间通信的机制,它允许不同组件之间通过发布/订阅模式进行通信,而不需要直接引用彼此。在Uniapp开发中,事件总线特别适合解决以下场景:
- 非父子组件间的通信
- 深层嵌套组件间的数据传递
- 全局状态变化的通知
二、创建事件总线
在Uniapp中创建事件总线非常简单:
1. 首先在项目中创建一个`eventBus.js`文件:
javascript
// utils/eventBus.js
class EventBus {
constructor() {
this.events = {};
}
// 监听事件
$on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
// 触发事件
$emit(eventName, ...args) {
const callbacks = this.events[eventName];
if (callbacks) {
callbacks.forEach(cb => cb(...args));
}
}
//移除监听器
$off(eventName, callback) {
const callbacks = this.events[eventName];
if (callbacks) {
if (callback) {
const index = callbacks.indexOf(callback);
if (index > -1) callbacks.splice(index,1);
} else {
delete this.events[eventName];
}
}
}
}
export default new EventBus();
2. Vue2/Vue3兼容版本:
javascript
import Vue from 'vue'
// Vue2使用方式(Vue3可使用mitt等库)
const eventBus = new Vue()
export default eventBus;
三、使用事件总线
1.基本使用方法
发送(触发)事件的组件:
javascript
import eventBus from '@/utils/eventBus';
methods: {
sendMessage() {
eventBus.$emit('message-event', { data: 'Hello World' });
}
}
接收(监听)事件的组件:
javascript
import eventBus from '@/utils/eventBus';
created() {
eventBus.$on('message-event', payload => {
console.log('收到消息:', payload.data); // Hello World
});
},
beforeDestroy() {
//记得移除监听避免内存泄漏!
eventbus.$off('message-event');
}
2.Vue3组合式API用法
对于Vue3项目,可以使用setup语法糖:
javascript
<script setup>
import { onMounted, onBeforeUnmount } from 'vue'
import eventbus from '@/utils/events'
const handleMessage=(data)=>{
console.log(data)
}
onMounted(()=>{
events.on("someEvent",handleMessage)
})
onBeforeUnmount(()=>{
events.off("someEvent",handleMessage)
})
</script>
四、实际应用场景示例
场景1:全局用户登录状态通知
登录成功后触发:
jsx harmony
// login.vue
async handleLogin(){
try{
await loginApi();
events.$emit('login-status-changed',true);
}catch(e){
console.error(e);
}}
其他页面监听:
// user-profile.vue
mounted(){
events.$on('login-status-changed',(isLoggedIn)=>{
this.showLogin=!isLoggedIn;
})
}
destroyed(){...} //清理!
场景2:跨页面表单数据传递
A页面向B页面传值
// pageA.vue
goToPageB(){
uni.navigateTo({
url:'pageB',
success(){
events.$emit('form-data',{name:'张三'})
}})
}
// pageB.vue
mounted(){
events.once('form-data',data=>{
console.log(data.name)//"张三"
})}
> 注意:这里使用了`$once`方法表示只监听一次
文章点评