看到一篇文章说 vue3 组件通信然后提到跨组件事件使用 mitt 这个没有毛病,也可以使用 vueuse 提供的 useEventBus
但是我对文中把 mitt 挂载到 app.config.globalProperties
上的这一个操作不是很认同
ts
import mitt from 'mitt'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.globalProperties.$bus = mitt()
app.mount('#app')
防杠 (ts + vue3 setup 项目),如果各位大佬有不同意见也欢迎留言讨论
原因如下
globalProperties
官方文档已经提示谨慎使用 = 约等于不推荐
这句话我的理解是应用如果真的需要一个全局访问的属性或者函数应该使用 provide / inject
app.config.globalProperties
是没有办法的办法-但凡有其他办法都不会去用它
再来看一下 globalProperties
ts 类型定义
ts
interface AppConfig { globalProperties: Record<string, any> }
挂载到 globalProperties
数据类型是 any,也就失去了 ts 类型提示(这个我觉得还是蛮重要的)
当然官方也提供了扩展 globalProperties
类型的方法 猛击直达链接
一个库在 ts 项目中没有类型提示不是约等于残废吗?
getCurrentInstance
假如你把属性挂载到 globalProperties
上要怎么使用呢?通过 getCurrentInstance
ts
<script setup>
import { getCurrentInstance, onMounted } from 'vue'
const { proxy } = getCurrentInstance()
onMounted(() => {
proxy.$bus.on('myEvent', (message) => {
console.log(message)
})
})
</script>
可是 getCurrentInstance
这个 API 在 2021 年就从文档移除了!
下边是一些 github 相关问题的回答
到这里大概可以说把 mitt 挂载到 vue3 的 globalProperties 上不是一个很明智的选择(你非要这么做俺也没办法)
或者说使用 app.config.globalProperties
getCurrentInstance
API 的时候要三思而后行!
mitt 使用的正确姿势
github 的说明文件给出了示例 猛击直达 npm
新建一个 mittBus.ts
文件把 emitter 导出
ts
import mitt from 'mitt'
type EventBus = {
test: {
text: string
status: boolean
}
test1: {
status: string
}
}
export const Bus = mitt<EventBus>()
在需要使用的地方导入然后使用
ts
import { emitter } from './components/mittBus.ts'
// 触发
emitter.emit('test', { text: 'test',status: true })
// 监听
emitter.on('test', (e) => {
console.log(e)
})
emitter.emit('test1', { status: 'test1' })
emitter.on('test1', (e) => {
console.log(e)
})
就这么简单,这样在使用的时候就会有 ts 类型提示
而且这个 mittBus.ts
文件不止可以创建一个,业务简单就创建一个全局唯一的一个所有事件都写在里边,如果业务复杂可以按照模块划分 aMiitt.ts
、bMitt.ts
然后在需要的地方引入使用
总结
把 mitt 挂载到 app.config.globalProperties
上使用 getCurrentInstance
不是一个推荐的做法, app.config.globalProperties
官方文档提示谨慎使用,getCurrentInstance
则是已经从文档中移除是 vue3 的内部 API 虽然仍可以导入使用但官方明确表示不希望用户在应用中使用
正确的做法是新建一个文件 mittBus.ts
然后把 emitter 导出这样可以获取良好的类型提示
更多也是让更多的人正确认识 app.config.globalProperties
和 getCurrentInstance
API
这里还有一篇 深入解析 mitt 和 vueuse useEventBus 的实现 可以了解 mitt 是如何实现的!