vue3.0的event hub替换方案- mitt 实操及mitt源码窥探

js在 2.x 中,Vue 实例可用于触发通过事件触发 API 强制附加的处理程序 ($on$off$once),这用于创建 event hub,以创建在整个应用程序中使用的全局事件侦听器:

然而

我们整个从实例中移除了 $on$off$once 方法,$emit 仍然是现有 API 的一部分,因为它用于触发由父组件以声明方式附加的事件处理程序

因实际项目中 都是用 event hub

例如下面业务代码

bus.$on('refrestatus' + this.data.oort_uuid, this.changeStatus)
this.$once('hook:destoryed', () => {  
    bus.$off('refrestatus' + this.data.oort_uuid, this.changeStatus)
})
bus.$on('refrestatus_false', this.changeStatus)
this.$once('hook:destoryed', () => {  
    bus.$off('refrestatus_false', this.changeStatus)
})

项目中bus 单独一个文件, 完全利用 Vue 的 $on $off 以及 $emit

import Vue from 'vue'

const bus = new Vue()

export default bus

但是现在vue 3.0 移除了这部分api

所以需求替代方案, vue3.0 给出的

例如,可以通过使用实现事件发射器接口的外部库来替换现有的 event hub mitt

所以ba la ba la 下这个库

感觉是 , 强 , 简单移动, 代码细节操作很给力

贴下我写了注释的源码


// 用到 es6的 symbol, 不局限于事件类型  为字符串
export type EventType = string | symbol;

// An event handler can take an optional event argument
// and should not return a value
export type Handler<T = any> = (event?: T) => void;
export type WildcardHandler = (type: EventType, event?: any) => void;

// An array of all currently registered event handlers for a type
export type EventHandlerList = Array<Handler>;
export type WildCardEventHandlerList = Array<WildcardHandler>;

// A map of event types and their corresponding event handlers.
export type EventHandlerMap = Map<EventType, EventHandlerList | WildCardEventHandlerList>;

export interface Emitter {
	all: EventHandlerMap;

	on<T = any>(type: EventType, handler: Handler<T>): void;
	on(type: '*', handler: WildcardHandler): void;

	off<T = any>(type: EventType, handler: Handler<T>): void;
	off(type: '*', handler: WildcardHandler): void;

	emit<T = any>(type: EventType, event?: T): void;
	emit(type: '*', event?: any): void;
}

/**
 * Mitt: Tiny (~200b) functional event emitter / pubsub.
 * @name mitt
 * @returns {Mitt}
 */
export default function mitt(all?: EventHandlerMap): Emitter {
	all = all || new Map();

	return {

		/**
		 * A Map of event names to registered handler functions.
		 */
		all,

		/**
		 * Register an event handler for the given type.
		 * @param {string|symbol} type Type of event to listen for, or `"*"` for all events
		 * @param {Function} handler Function to call in response to given event
		 * @memberOf mitt
		 */
		on<T = any>(type: EventType, handler: Handler<T>) {
			const handlers = all.get(type);
			const added = handlers && handlers.push(handler);  // 短路运算符  妙哉
			if (!added) {
				all.set(type, [handler]);
			}
		},

		/**
		 * Remove an event handler for the given type.
		 * @param {string|symbol} type Type of event to unregister `handler` from, or `"*"`
		 * @param {Function} handler Handler function to remove
		 * @memberOf mitt
		 */
		off<T = any>(type: EventType, handler: Handler<T>) {
			const handlers = all.get(type);
			if (handlers) {
				 // 右移运算符,正数右移 返回原值,负数右移,变正数; 这里indexOf 即使返回-1, -1>>>0 = 4294967295
				 // 这种写法,我写的话,无脑就上if 了,哪有这个高级, 感叹!!!
				handlers.splice(handlers.indexOf(handler) >>> 0, 1);
			}
		},

		/**
		 * Invoke all handlers for the given type.
		 * If present, `"*"` handlers are invoked after type-matched handlers.
		 *
		 * Note: Manually firing "*" handlers is not supported.
		 *
		 * @param {string|symbol} type The event type to invoke
		 * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler
		 * @memberOf mitt
		 */
		emit<T = any>(type: EventType, evt: T) {
			// slice() 返回一个新数组,可理解为复制这里;这里的用法还是没有很明白为什么要这样用;求给位大佬解答
			((all.get(type) || []) as EventHandlerList).slice().map((handler) => { handler(evt); });
			((all.get('*') || []) as WildCardEventHandlerList).slice().map((handler) => { handler(type, evt); });
		}
	};
}

最后看下如何替换的

import mitt from 'mitt'

const bus = {}

const emitter = mitt()

bus.$on = emitter.on
bus.$off = emitter.off
bus.$emit = emitter.emit

export default bus

欢迎各位指正

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue 3.0是一种流行的JavaScript框架,用于构建用户界面。它具有响应式数据绑定和组件化的特性,使得开发者可以更轻松地构建交互式的Web应用程序。 Vue-video-player是一个基于Vue.js的视频播放器组件,它提供了一种简单的方式来在Vue应用程序中嵌入视频播放功能。它支持多种视频格式,包括MP4、WebM和Ogg等,并且提供了丰富的功能选项,如自定义控制条、全屏模式、播放速度调节等。 使用vue-video-player,你可以按照以下步骤来集成视频播放器到你的Vue 3.0应用程序中: 1. 首先,安装vue-video-player包。你可以使用npm或者yarn来进行安装: ``` npm install vue-video-player ``` 或者 ``` yarn add vue-video-player ``` 2. 在你的Vue组件中引入vue-video-player: ```javascript import VueVideoPlayer from 'vue-video-player'; import 'video.js/dist/video-js.css'; // 引入视频播放器样式 import 'vue-video-player/src/custom-theme.css'; // 引入自定义主题样式 export default { components: { VueVideoPlayer, }, // ... } ``` 3. 在模板中使用vue-video-player组件: ```html <template> <div> <vue-video-player :options="playerOptions"></vue-video-player> </div> </template> ``` 4. 在Vue组件的data选项中定义视频播放器的配置选项: ```javascript export default { data() { return { playerOptions: { sources: [{ src: 'path/to/your/video.mp4', type: 'video/mp4', }], // 其他配置选项... }, }; }, // ... } ``` 这样,你就可以在Vue应用程序中使用vue-video-player来播放视频了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值