之前没太关注过组件之间的数据传递问题,一般做项目如果是Vue2.x版本,直接用Vuex。
如果是Vue3.x版本,直接用Pinia。基本上很少用Bus(事件总线),也没太关注过其他方案。

问题
最近做一个不大不小的项目,本来想着直接用 Pinia 了,但是页面有点儿少,用 Pinia 感觉有点儿杀鸡用牛刀。
所以就选择用 props 传值的方式,但是兄弟组件的传值害惨我了。

遂看一下网上的方案,兄弟组件的传值大概有三种手段:
- 最传统的
Props传值的方案。 - 简单粗暴的
Bus事件总线方案。 - 封装好的库
Mitt传参方案。
Props方案
最为传统的传参方案,父子组件之间传参非常好用。封装组件也是相当哇塞,但是在兄弟组件之间传参太过复杂。
尤其是从 A 组件的子组件 A1 上,传递参数到 B 组件的子组件 B1 上。层层转发。
写起来太过麻烦,而且用起来也不方便,每改一个参数需要四个组件同时修改。

Bus方案
我个人在团队内部不喜欢大家使用 Bus ,原因很简单,不易维护。
定义的 Bus 如果在好几个地方使用很难得到有效的控制,出现问题也很难快速定位。
并且我发现好几个小兄弟在写 Bus 的时候都忘记使用 $off 移除监听了,很容易造成应用内存泄漏。
另外就是在开发过程中 VsCode 和 WebStorm 是不支持通过 ctrl + 点击 寻找对应方法的,开发体验也一般情况。
最最重要的是,在Vue3.x版本中已经正式移除了 Bus 的API。
Mitt方案
Mitt这个方案我目前在正式的项目中还没用过,只是简单在几个Demo中尝试用了用。
怎么说呢,非常简洁!

一共就三个方法:
js
import mitt from 'mitt'
const emitter = mitt();
// 发送事件
emitter.emit('custom-event', 'Hello from A')
// 接收事件
emitter.on('custom-event', handler)
// 移除事件
emitter.off('custom-event', handler)
能看得到的优点:小(200多kb)、无依赖、Ts友好,但是缺点也同样明显:
- 创建的事件全局共享,可能存在事件名冲突。
- 需要手动调用
off移除监听。 - 调试追踪困难
- 异步问题
Mitt和Bus的区别
看Mitt的缺点和Bus的缺点几乎一致,那么他俩到底有区别嘛?
还是说尤老师看到现成的直接对这部分代码不重写了?😂
先说答案:Mitt和Bus是存在本质性区别的。
原理不同
Mitt是一个独立的Js库,无任何相关依赖,在任何环境都可以使用。Vue、React、原生Js等都能用。
在Mitt的内部手动维护了一个事件的映射表Map<string, Function[]>。
而Bus依赖于Vue2.x的内部API,其原理上是基于Vue的观察者模式。

使用不同
虽然他们大部分的用法非常相似,比如说事件发送,一个用 $emit,一个用 emit()。
但是也存在很多区别。
Bus 不支持通配符监听,而 mitt 可以通过 mitt.on('*', ()=>{}) 的方式实现通配符的监听。
并且 mitt 支持Ts,这是最关键的。毕竟现在绝大多数的新应用在开发的时候都要求使用Ts。
总结
如果是老项目,我仍然推荐原来用啥就用啥。
如果是新项目,并且上了Vue3.x版本,那么你除了mitt恐怕没有别的选择(小项目)。Vue3.x 版本移除了 Bus!
另外需要强调的是 mitt 是临时通信 ,也就是说它只是一个临时方案 。如果你所在的是一个大项目,我劝你仍然稳妥的使用 Pinia。