安卓端Chrome93点击浏览器返回键未触发popstate事件问题求助
问题根因
- 安卓Chrome 93及以上版本对无用户交互触发的
pushState操作做了策略限制,页面加载初期同步执行的pushState如果传入空state、且未关联任何用户行为,会被浏览器判定为非用户主动产生的无效历史记录,返回时会直接跳过该条记录,导致popstate事件完全不触发。 - Vue 2单页应用如果使用了vue-router,路由自身的历史栈操作和手动调用的
pushState存在时序冲突,也会导致手动插入的历史记录失效。
修复方案
方案1:调整原生popstate监听逻辑
调整pushState的参数和执行时机,同时补充历史记录重入逻辑,兼容安卓Chrome的策略限制:
mounted() { // 等待Vue异步更新队列清空后执行,避免和路由的历史操作冲突 this.$nextTick(() => { // 避免重复插入相同的自定义历史记录 if (history.state?.isCustomBackGuard) return // 传入非空的state标识,避免被Chrome判定为无效历史记录 history.pushState({ isCustomBackGuard: true }, null, location.href) }) const handlePopstate = () => { alert('触发返回拦截') // 此处执行你的自定义操作 // 若需要继续拦截下一次返回,重新插入自定义历史记录即可 history.pushState({ isCustomBackGuard: true }, null, location.href) // 若自定义操作完成后需要正常返回上一页,取消注释下面的代码 // history.back() } window.addEventListener('popstate', handlePopstate) // 页面销毁前移除事件监听,避免内存泄漏 this.$once('hook:beforeDestroy', () => { window.removeEventListener('popstate', handlePopstate) }) }
方案2:使用Vue路由守卫(更推荐)
如果你的项目使用了vue-router,优先使用内置的路由守卫实现返回拦截,兼容性和逻辑一致性更好,无需手动操作历史栈:
export default { // ...其他组件选项 beforeRouteLeave(to, from, next) { // 此处执行你的自定义操作 alert('触发返回拦截') const allowLeave = false // 替换为你的自定义判断逻辑 if (allowLeave) { next() // 允许离开当前页,返回上一级 } else { next(false) // 阻止离开,停留在当前页 } } }
补充注意事项
如果页面的返回拦截需要在用户完成特定操作后才激活,建议将pushState逻辑放到用户首次触摸、点击页面的事件回调中执行,和用户行为关联后,安卓Chrome的兼容表现会更稳定。
内容的提问来源于stack exchange,提问作者Cuckoos
相关产品推荐
相关产品推荐

