一、背景知识
Vue2
使用 EventBus
进行组件通信,而Vue3
移除了 $on $off
等自带的自定义事件相关方法,因此在 Vue3
中推荐下载mitt
库来使用事件总线传递数据。
比起 Vue
实例上的 EventBus
,mitt.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); });
}
};
}