访问Vue 3项目时Edge无法最小化回弹问题解决方法

问题描述

项目框架:Nuxt 3 (Vue 3 + Nitro)

浏览器:Edge 145.0.3800.97(2026年3月11日 检测的最新版本)

今天项目迭代时,突然出现的情况,浏览器无法最小化,表现为最小化时会成功,但是立马又弹出来。

疑点如下:

只有当前激活的标签页访问的是该项目时才会复现(本地运行或部署的远程环境都可以),切换到其他标签页就没事
其他浏览器没事,Edge 的问题
代码回退到前几天没出问题的时候,仍能复现
初步分析结果:

Edge 可能发生过更新(最近没有动过配置)
其他页面没问题,应该是项目中代码触发了问题

定位问题

垃圾 Edge 没办法动,只能去代码中找找是哪里触发了。

既然是页面最小化时触发的问题,那先监听一下浏览器事件,编写了一个脚本去查看注册了那些事件,并在触发的时候打印下回调函数内容:

function monitorExistingEventListeners() {
  console.log('🎯 监控已有事件监听器...')

  if (typeof getEventListeners !== 'function') {
    console.error('❌ API getEventListeners 不可用')
    return
  }

  // 监控的目标元素
  const targets = [window, document]

  targets.forEach(target => {
    const listeners = getEventListeners(target)
    const eventTypes = Object.keys(listeners)

    console.log(`📋 ${target === window ? 'window' : 'document'} 事件:`)

    eventTypes.forEach(eventType => {
      const eventListeners = listeners[eventType]

      console.log(`   📍 ${eventType}: ${eventListeners.length} 个监听器`)

      eventListeners.forEach((listenerInfo, index) => {
        // 替换监听器
        const originalListener = listenerInfo.listener

        const wrappedListener = function (...args) {
          console.log(`📢 [${eventType}] 触发`)
          console.log(`       函数: ${listenerInfo.listener.toString()}.`)

          // 执行原始监听器
          return originalListener.apply(this, args)
        }

        // 移除原监听器,添加包装后的监听器
        target.removeEventListener(eventType, originalListener, listenerInfo.useCapture)
        target.addEventListener(eventType, wrappedListener, listenerInfo.useCapture)
      })
    })
  })

  console.log('✅ 已有事件监听器监控已启动')
}

// 立即执行
monitorExistingEventListeners()

页面加载完后,在粘贴到控制台执行,结果如下:

操作一下最小化,控制台日志如下:

移除这个 visibilitychange 事件后,最小化就正常了:

const listeners = getEventListeners(document).visibilitychange
if (listeners && listeners.length > 0) {
  listeners.forEach(listener => {
    document.removeEventListener('visibilitychange', listener.listener)
  })
  console.log('已移除 visibilitychange 监听器')
}

接着全局搜 beforeUnloadListener 方法,看看是哪里调用的,原来是 vue router 的代码:

问题应该是出现在 history.replaceState 这里,尝试重写它的逻辑:

// 这块代码写在引入 vue router 之后
const originalReplaceState = window.history.replaceState

window.history.replaceState = function (state, title, url) {
  console.log('🚨 history.replaceState 被调用,已拦截')
  // originalReplaceState.call(this, {}, '', '')
  originalReplaceState.call(this, null, '', '')
}

测试结果:当 replaceState 接收的第一个参数不为空时就会复现,即修改历史记录会复现。

模拟问题复现

为了进一步确认问题仅来源于 history.replaceState 方法,编写一个 demo 去复现:

一开始直接用本地文件访问的方式(浏览器直接打开文件:File 协议)打开,并没有复现。

后来反复对比了 vue router 代码没有发现什么差异,想到可能是运行方式不同,于是用 Live Server 起了个服务再去访问,终于复现成功了。

尝试了下 pushState 也能复现。

临时解决

至此事情已经搞清楚了:垃圾 Edge 在处理页面的历史状态更新时,可能触发了内部的 “页面激活” 机制。

查不到 Edge 有没有配置能够修改这个,Edge 动不了。

beforeUnloadListener 是 vue router 一直都有的重要逻辑,回退版本也存在。

为了不影响客户正常访问,暂时只能先把 replaceState 重写,等 Edge 修正了这个问题再把功能还原:

window.history.replaceState = function () {
  console.log('🚨 history.replaceState 被调用,已拦截')
  return
}

垃圾Edge!!!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇