Vue3 使用 mitt.js (事件总线)

1,417 阅读2分钟

一、背景知识

Vue2 使用 EventBus 进行组件通信,而Vue3移除了 $on $off 等自带的自定义事件相关方法,因此在 Vue3 中推荐下载mitt库来使用事件总线传递数据。

比起 Vue 实例上的 EventBusmitt.js 好在哪里呢?首先它足够小,仅有200bytes,其次支持全部事件的监听和批量移除,它还不依赖 Vue 实例,所以可以跨框架使用,React 或者 Vue,甚至 jQuery 项目都能使用同一套库。

二、安装mitt库

npm i mitt

三、使用mitt库

1.封装自定义事务总线文件 eventbus.js。

// mitt库默认导出的是一个函数,我们需要执行它从而得到事件总线的对象
/* eventbus.js */
// 这里我们在js中暴露这个事件总线对象
import mitt from "mitt";
const emitter = mitt();
export default emitter;

2.在指定组件中导入并使用

/* About.vue */

<button @click="sendHomeContent">send</button>  

// 导入事件总线
import emitter from "./utils/eventbus.js";  
// methods代码
sendHomeContent(){
    // 触发自定义总线why,并传入一个对象
     emitter.emit("why",{name:'why',age:19})
}
/* HomeContent.vue */

// 导入事件总线
import emitter from "./utils/eventbus.js";

// 在创建vue实例时,注册why事件总线
created(){
    emitter.on("why",msg=>{
        console.log("HomeContent接收到得About发送得数据了:",msg);
    });
}

四、mitt其他用法

1.监听所有事件

// emitter.on的第一个参数如果是 * 代表监听所有的事件触发!
// 这时,回调函数的参数就会有2个,1是事件的类型,2是实际实参
emitter.on("*",(eventType,item)=>{
 console.log(`* 监听到的事件类型是:${eventType},接收的参数为:`,item)
})

2.事件取消

// 1.取消所有的mitt事件
emitter.all.clear()

// 2.取消指定的mitt事件
// 需要取消指定事件的监听,需要将回调定义在外部,类似于setTimeout
function onFoo(){}
emitter.on('foo',onFoo) //监听
emitter.off('foo',onFoo) //取消监听

五、总结步骤

1.注册并监听自定义事件
emitter.on(eventType,callback)
2.触发自定义事件
emitter.emit(eventType,params)

六核心原理

export default function mitt(all) {
	all = all || new Map();

	return {
		all,

		on(type, handler) {
			const handlers = all.get(type);
			const added = handlers && handlers.push(handler);
			if (!added) {
				all.set(type, [handler]);
			}
		},

		off(type, handler) {
			const handlers = all.get(type);
			if (handlers) {
				handlers.splice(handlers.indexOf(handler) >>> 0, 1);
			}
		},

		emit(type, evt) {
			((all.get(type) || [])).slice().map((handler) => { handler(evt); });
			((all.get('*') || [])).slice().map((handler) => { handler(type, evt); });
		}
	};
}