使用 Object.defineProperty 解决 window.onload 被覆盖的问题

423 阅读1分钟

手头上有个 vue 项目,一些不同的 js 包 被加载到了同一个页面,导致一个页面里可能有一个以上的 window.onload ,这样做的后果就是前面的回调函数会被后面的覆盖掉。

微信截图_20220120163657.png 大多数情况下的解决方案有:

  1. 重写 window.onload 方法;
  2. 使用 window.addEventListener ;
  3. 使用setTimeout

但对于引入的js来说无法修改代码,以上方式都不适用,于是利用 Object.defineProperty 劫持 window.onload 的赋值行为,把对应的回调函数放到一个队列中进行处理。

    const eventQueue = []
    Object.defineProperty(window, 'onload', {
      set(fn) {
        fn instanceof Function && eventQueue.push(window.onload);
        console.log('eventQueue添加了回调', fn);
      }
    })

//  需在页面加载完成后执行
    setTimeout(() => {
      eventQueue.forEach(fn => {
        // 执行回调

        try {
          fn.call(window)

        } catch (error) {
          console.log(error);
        }
      })
    }, 0);