东湖之滨 发表于 2025-3-12 17:44:54

vue3中事件总线

在 Vue 3 中,eventBus 的概念已经被弱,不保举使用全局事件总线,
你需要一个轻量级的事件总线,可以自己封装一个 EventBus 类,也有一些替换方案
1、使用第三方库(如 mitt 或 tiny-emitter)

mitt 是一个轻量级的事件发射器,适合在 Vue 3 中替换事件总线。它不依赖 Vue 实例,体积小且易于使用。
npm install mitt
// src/utils/eventBus.js
import mitt from 'mitt';

export const emitter = mitt();
import { emitter } from './utils/eventBus';
// 触发事件
emitter.emit('event-name', data);
// 取消监听
emitter.off('event-name', handler);
2、依赖注入

provide 和 inject 是 Vue 3 保举的父子组件通信方式,适合在组件树中传递数据。
// 父组件
import { provide } from 'vue';
export default {
setup() {
    provide('message', 'Hello from Parent');
}
};
// 子组件
import { inject } from 'vue';
export default {
setup() {
    const message = inject('message');
    console.log(message);
}
};
3、使用vuex或者pina

对于复杂的状态管理,保举使用 Vuex 或 Pinia。它们提供了更强大的状态管理能力,适合大型项目。
// store.js
import { createStore } from 'vuex';
export default createStore({
state: {
    message: 'Hello from Vuex'
},
mutations: {
    updateMessage(state, payload) {
      state.message = payload;
    }
}
});
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 是最直接的方式。
<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>
<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 实例作为事件总线来实现类似的功能。
// 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) {
      this.events = [];
    }
    this.events.push(callback);
},

emit(event, ...args) {
    if (this.events) {
      this.events.forEach(callback => {
      callback(...args);
      });
    }
},

off(event, callback) {
    if (this.events) {
      this.events = this.events.filter(cb => cb !== callback);
    }
}
};

export default eventBus;
子组件
// 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) {
      this.events = [];
    }
    this.events.push(callback);
},

emit(event, ...args) {
    if (this.events) {
      this.events.forEach(callback => {
      callback(...args);
      });
    }
},

off(event, callback) {
    if (this.events) {
      this.events = this.events.filter(cb => cb !== callback);
    }
}
};

export default eventBus;
父组件:
<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>
使用类方法封装一个事件总线
// src/utils/EventBus.js

class EventBus {
constructor() {
    this.events = {};
}

/**
   * 监听事件
   * @param {string} event - 事件名称
   * @param {Function} callback - 回调函数
   */
$on(event, callback) {
    if (!this.events) {
      this.events = [];
    }
    this.events.push(callback);
}

/**
   * 触发事件
   * @param {string} event - 事件名称
   * @param {...any} args - 传递给回调函数的参数
   */
$emit(event, ...args) {
    if (this.events) {
      this.events.forEach(callback => {
      callback(...args);
      });
    }
}

/**
   * 移除事件监听
   * @param {string} event - 事件名称
   * @param {Function} callback - 回调函数
   */
$off(event, callback) {
    if (this.events) {
      this.events = this.events.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;
子组件
<template>
<button @click="handleClick">点击我</button>
</template>

<script>
import eventBus from '../utils/EventBus';

export default {
methods: {
    handleClick() {
      // 触发事件
      eventBus.$emit('custom-event', 'Hello from Child');
    }
}
}
</script>
父组件
<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>

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: vue3中事件总线