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
欢迎各位指正