直接上代码:
import { noop } from 'lodash';
const rawAddEventListener = window.addEventListener;
const rawRemoveEventListener = window.removeEventListener;
这里先保存window的添加和移除监听的函数。
export default function hijack() {
const listenerMap = new Map<string, EventListenerOrEventListenerObject[]>();
window.addEventListener = (
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
) => {
const listeners = listenerMap.get(type) || [];
listenerMap.set(type, [...listeners, listener]);
return rawAddEventListener.call(window, type, listener, options);
};
...
函数名很显而易见的知道这个函数的功能,函数劫持(其实就是改写函数,在执行的时候保留原本功能并加上我们想要的副作用)。
函数里面声明了listenerMap来保存监听器,
并改写了window.addEventListener.在执行原本功能的时候往listenerMap上加入当前监听器。
window.removeEventListener = (
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
) => {
const storedTypeListeners = listenerMap.get(type);
if (storedTypeListeners && storedTypeListeners.length && storedTypeListeners.indexOf(listener) !== -1) {
storedTypeListeners.splice(storedTypeListeners.indexOf(listener), 1);
}
return rawRemoveEventListener.call(window, type, listener, options);
};
这里改写了removeEventListener并且在listenerMap上删除原本的回调函数。
return function free() {
listenerMap.forEach((listeners, type) =>
[...listeners].forEach(listener => window.removeEventListener(type, listener)),
);
window.addEventListener = rawAddEventListener;
window.removeEventListener = rawRemoveEventListener;
return noop;
};
}
最后该函数返回一个重置window事件监听功能的函数。
qiankun git链接 : https://github.com/umijs/qiankun