微前端框架qiankun源碼解讀 -1.1 hijackers/windowListener

 直接上代碼:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章