Vue3.x 推荐使用 mitt.js

摘要:比起 Vue 实例上的 EventBus,mitt.js 好在哪里呢?首先它足够小,仅有200bytes,其次支持全部事件的监听和批量移除,它还不依赖 Vue 实例,所以可以跨框架使用,React 或者 Vue,甚至 jQuery 项目都能使用同一套库。

Vue2.x 使用 EventBus 进行组件通信,而 Vue3.x 推荐使用 mitt.js。

比起 Vue 实例上的 EventBus,mitt.js 好在哪里呢?首先它足够小,仅有200bytes,其次支持全部事件的监听和批量移除,它还不依赖 Vue 实例,所以可以跨框架使用,React 或者 Vue,甚至 jQuery 项目都能使用同一套库。


快速开始

npm install --save mitt

方式1,全局总线,vue 入口文件 main.js 中挂载全局属性。

import { createApp } from 'vue';
import App from './App.vue';
import mitt from "mitt"

const app = createApp(App)
app.config.globalProperties.$mybus = mitt()

方式2,封装自定义事务总线文件 mybus.js,创建新的 js 文件,在任何你想使用的地方导入即可。

import mitt from 'mitt'
export default mitt()

方式3,直接在组件里面导入使用。推荐大家使用这种方式,因为分散式更方便管理和排查问题。

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Hello Vue 3.0 + Vite" />
</template>

<script>
import mitt from 'mitt'
import HelloWorld from './components/HelloWorld.vue'

export default {
  components: {
    HelloWorld
  },
  setup (props) {
    const formItemMitt = mitt()
    return {
      formItemMitt
    }
  }
}
</script>

使用方式

其实 mitt 的用法和 EventEmitter 类似,通过 on 方法添加事件,off 方法移除,clear 清空所有。

import mitt from 'mitt'

const emitter = mitt()

// listen to an event
emitter.on('foo', e => console.log('foo', e) )

// listen to all events
emitter.on('*', (type, e) => console.log(type, e) )

// fire an event
emitter.emit('foo', { a: 'b' })

// clearing all events
emitter.all.clear()

// working with handler references:
function onFoo() {}
emitter.on('foo', onFoo)   // listen
emitter.off('foo', onFoo)  // unlisten

需要注意的是,导入的 mitt 我们是通过函数调用的形式,不是 new 的方式。在移除事件的需要传入定义事件的名字和引用的函数。


核心原理

原理很简单,就是通过 map 的方法保存函数。经过我的删减代码不到 30 行。

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); });
		}
	};
}

Vue3 从实例中完全删除了 $on、$off 和 $once 方法。$emit 仍然是现有API的一部分,因为它用于触发由父组件以声明方式附加的事件。



本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_10449