Vue.js项目中如何区分用户关闭标签、跳转页面还是刷新页面
你之前的判断逻辑失效的核心原因是:beforeunload触发时读取的performance.navigation.type/PerformanceNavigationTiming.type记录的是当前页面的加载来源,不是本次页面卸载的触发原因,所以三种场景下拿到的都是上一次导航的结果,自然无法区分。
以下是可落地的实现方案:
方案1:基于SessionStorage区分刷新/关闭,实现成本最低
SessionStorage的生命周期和当前标签页绑定,页面刷新时数据保留,关闭标签/浏览器后自动清空,刚好匹配你的需求:
created() { // 页面加载时判断是否为刷新场景 const isRefresh = sessionStorage.getItem('game_session_active') === 'true' if (isRefresh) { // 刷新场景,直接恢复现有Firestore游戏数据即可 this.restoreGameState() } else { // 首次进入/关闭后重新进入,清理残留的旧游戏数据 this.clearObsoleteGameData() } // 标记当前会话激活 sessionStorage.setItem('game_session_active', 'true') // 注册beforeunload监听 window.addEventListener("beforeunload", (event) => { this.stopFirestoreListeners("beforeunload") // 不需要在这里删除Firestore文档: // 1. 刷新场景下SessionStorage标记保留,下次加载会识别为刷新,不会清理数据 // 2. 关闭/跳转场景下SessionStorage自动清空,下次加载会触发旧数据清理 }); // 处理浏览器bfcache回退场景 window.addEventListener('pageshow', (event) => { if (event.persisted) { this.startFirestoreListeners("pageshow") } }) this.startFirestoreListeners("created"); }
方案2:配合Firestore原生能力,可靠性更高
前端beforeunload事件本身不可靠,浏览器可能直接终止页面进程,导致你写的删除逻辑没机会执行。针对你用Firestore的场景,直接用官方提供的onDisconnect断连触发机制更稳妥:
// 初始化游戏文档后设置断连操作 const gameDocRef = db.collection('games').doc(this.gameId) // 配置断开连接1分钟后自动删除文档,给刷新预留足够的重连时间 await gameDocRef.onDisconnect().set({ autoDeleteAfter: Date.now() + 60 * 1000 }, { merge: true }) // 页面加载完成后,验证游戏文档状态 const gameDoc = await gameDocRef.get() if (gameDoc.exists && gameDoc.data().autoDeleteAfter > Date.now()) { // 刷新场景,取消之前的断连删除计划,保留文档 await gameDocRef.onDisconnect().cancel() await gameDocRef.update({ autoDeleteAfter: FieldValue.delete() }) this.restoreGameState(gameDoc.data()) } else { // 新会话场景,创建新的游戏文档 this.createNewGame() }
补充:区分跳转页面场景
如果需要单独识别用户点击链接/提交表单跳转的场景,可以提前加全局标记:
// 全局标记是否为主动跳转 let isActiveNavigation = false // 监听链接点击 document.addEventListener('click', (e) => { if (e.target.tagName === 'A' && new URL(e.target.href).origin === window.location.origin) { isActiveNavigation = true } }) // 监听表单提交 document.addEventListener('submit', () => { isActiveNavigation = true }) // beforeunload里判断类型 window.addEventListener('beforeunload', () => { if (isActiveNavigation) { // 主动跳转场景逻辑 } })
内容的提问来源于stack exchange,提问作者Loren
相关产品推荐
相关产品推荐

