核心内容摘要
探秘“伽罗ドラえもんの脚法hibjn”:解锁无限可能的新纪元
mitt 简介在 Vue 应用中我们经常遇到这样的情况两个组件之间没有直接的父子关系但需要共享数据或者互相通信。
比如一个页面中的头部组件需要知道用户点击了侧边栏的某个菜单项。
这时候使用 props 和事件会非常麻烦因为需要经过多层组件的传递。
mitt 就是为了解决这种问题而存在的。
mitt 是一个小巧的 JavaScript 事件发射器库它只有 200 字节左右但功能非常强大。
它允许我们在任意组件之间建立通信无论这些组件在组件树中的位置如何。
你可以把 mitt 想象成一个事件广播系统任何组件都可以在这个系统上发送消息也可以监听其他组件发送的消息。
mitt 的优势mitt非常轻量API 简洁专门为现代 JavaScript 设计是 Vue 3 社区中最流行的事件总线方案。
它的 API 只有三个方法on监听事件、emit触发事件、off取消监听学习成本很低。
使用教程安装 mitt打开终端在项目根目录下运行npm i mitt建立文件为了让整个应用都能使用同一个事件总线我们通常会在一个单独的文件中创建 mitt 实例然后导出这个实例供其他模块使用。
在项目的 utils 文件夹中如果没有就创建一个新建一个名为 emitter.ts 的文件// utils/emitter.ts // 导入 mitt import mitt from mitt // 创建一个 mitt 实例 // 这个实例就是我们的事件总线所有组件都通过它与其它组件通信 const emitter mitt() // 导出这个实例 export default emitter这个文件的作用是创建一个全局的事件总线实例。
我们在整个应用中都会使用这个实例这样所有组件才能在同一个广播系统中通信。
mitt 的基本 API在开始使用之前我们先了解一下 mitt 的三个核心方法emitter.on(eventName, callback)监听事件。
当名为 eventName 的事件被触发时callback 函数会被调用。
emitter.emit(eventName, data)触发事件。
触发名为 eventName 的事件并将 data 数据传递给所有监听该事件的回调函数。
emitter.off(eventName, callback)取消监听事件。
移除对 eventName 事件的监听。
如果不传递 callback 参数则会移除该事件的所有监听函数。
实例假设我们有两个兄弟组件哥哥组件和弟弟组件。
哥哥想要给弟弟传递一个数据。
首先我们分析一下通信流程接收数据的组件弟弟需要提前监听事件准备好接收数据。
发送数据的组件哥哥在合适的时候触发事件并传递数据。
首先在弟弟组件中监听事件!-- BrotherYounger.vue -- template div classyounger h3弟弟组件/h3 p从哥哥那里接收到的数据/p /div /template script setup import { ref, onMounted, onUnmounted } from vue // 导入事件总线实例 import emitter from /utils/emitter const receivedData ref() // 组件挂载后开始监听事件 onMounted(() { // 监听名为sendA的事件 // 当这个事件被触发时回调函数会被调用参数value就是传递过来的数据 emitter.on(sendA, (value) { receivedData.value value console.log(弟弟收到了数据, value) }) }) // 组件卸载前取消事件监听 onUnmounted(() { emitter.off(sendA) }) /script在弟弟组件中我们做了以下几件事
导入事件总线实例 emitter。
在 onMounted 生命周期钩子中使用 emitter.on 监听名为 sendA 的事件。
当这个事件被触发时回调函数会被调用参数 value 就是哥哥组件传递过来的数据。
在 onUnmounted 生命周期钩子中使用 emitter.off 取消对 sendA 事件的监听。
这一步非常重要可以避免内存泄漏。
然后在哥哥组件中触发事件!-- BrotherElder.vue -- template div classelder h3哥哥组件/h3 button clicksendDataToYounger给弟弟发送数据/button /div /template script setup // 导入事件总线实例 import emitter from /utils/emitter const sendDataToYounger () { const data 这是哥哥发送的数据A // 触发名为sendA的事件并传递数据 emitter.emit(sendA, data) console.log(哥哥发送了数据, data) } /script在哥哥组件中我们做了以下几件事
导入事件总线实例 emitter。
定义一个方法 sendDataToYounger当按钮被点击时调用这个方法。
在方法中使用 emitter.emit 触发名为 sendA 的事件并传递数据。
现在当用户点击哥哥组件中的按钮时sendA 事件会被触发。
弟弟组件监听到这个事件就会执行回调函数将接收到的数据赋值给 receivedData 变量这样模板中就会显示这个数据。
重要
注意事项及时解绑事件使用 mitt 时有一个非常重要的
注意事项一定要在组件卸载时解绑事件。
如果不解绑即使组件已经被销毁它的事件监听函数仍然存在于事件总线中。
这会导致两个问题
内存泄漏监听函数一直存在无法被垃圾回收器回收。
错误调用当事件再次被触发时会调用到已经不存在的组件的函数可能导致错误。
因此我们一定要在 onUnmounted 生命周期钩子中解绑事件。
如果组件监听了多个事件可以分别解绑onUnmounted(() { emitter.off(sendA) emitter.off(sendB) // ... 解绑所有监听的事件 })参考文章https://blog.csdn.net/2301_80216352/article/details/155522600