能看到Vue3文章的各位,相信
eventBus
大家都不陌生。eventBus
—— 事件总线,作为Vue2.x兄弟组件通信的方案。但在Vue3中,eventBus
已经被官方移除,官方推荐的是更为专业的mitt
工具。
兄弟组件通信
场景
用户在个人信息页修改了自己的昵称信息,在页面发送请求服务器响应请求后,页面各个组件主动修改各组件中的昵称信息。例子如下图 ⬇
在图中每一个红色框都代表同一个页面里的一个组件,我们则需要在用户修改昵称之后,同时修改左侧工具栏以及顶部导航栏的昵称数据,这时就可以用mitt
工具库。
下载和引入
首先是下载依赖包⬇
npm i mitt --save
然后是引入,引入方式可以有两种⬇
// 第一种是创建一个工具js,不如说mitt.js,哪个组件要用到就引入该文件就好了。
import mitt from 'mitt'
const emitter = mitt()
export default emitter
// 第二种是像Vue2.x一样直接挂载一个全局的变量,不过这种方式官方说谨慎使用不推荐,感觉是维护性、性能方面的问题吧。
import { createApp } from 'vue'
import mitt from 'mitt'
import App from './App.vue'
const app = createApp(App)
const myMitt = mitt()
app.config.globalProperties.$myMitt = myMitt
使用
使用方面的话就和当初的eventBus
大同小异了。
//第一种工具函数引入方式
//兄弟组件一(发布事件)
<script setup>
import mitt from '@/utils/mitt'
const emitter = mitt
emitter.on('xxx',(value)=>{
console.log(value)
})
</script>
//兄弟组件二(订阅事件)
<script setup>
import mitt from '@/utils/mitt'
const emitter = mitt
emitter.emit('xxx','你好!')
</script>
// 第二种全局挂载方式
//兄弟组件一(发布事件)
<script setup>
//setup语法糖写法需要使用getCurrentInstance获取执行上下文,不是语法糖写法好像是setup(props,context)就可以获取到
import { getCurrentInstance } from "vue"
const cxt = getCurrentInstance() //获取 this
const emitter = cxt.appContext.config.globalProperties.$myMitt
emitter.on('xxx',(value)=>{
console.log(value)
})
</script>
//兄弟组件二(订阅事件)
<script setup>
import { getCurrentInstance } from "vue"
const cxt = getCurrentInstance() //获取 this
const emitter = cxt.appContext.config.globalProperties.$myMitt
emitter.emit('xxx','你好!')
</script>
总结
按我的理解,我觉得无论是
eventBus
还是mitt
它们都是一种订阅发布模式,也就是说这种通信方式是相对无敌的。不单单只是兄弟组件通信,你可以在任何组件on
订阅事件行为,在任何组件emit
发布事件行为,实现父子通信、父子孙通信等等。但是这种通信方式也是有弊端的,订阅发布模式的实现是一个闭包,统一管理着一个事件对象,如果项目中过度依赖这种通信方式,里面的事件对象就会变得十分之大,长期占用内存。同时你也可以想象一下,发布一个事件行为需要一个事件名及回调函数,项目各种组件都在依赖这种通信方式,各种事件名混淆在一起,项目的代码可读性会变得十分之差。所以说,专业的还得专业的来,在一些典型的业务场景下使用mitt
通信,才能让mitt
工具库发挥它最大的威力!
文章有问题之处还望评论斧正!
更多其他组件间通信文章链接放在下方⬇
Vue3组件间通信知识整理——父组件向子组件传参
Vue3组件间通信知识整理——子组件向父组件传参
Vue3组件间通信知识整理——父组件调用子组件方法