You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js/Quasar框架如何监听浏览器关闭事件上报用户离线状态

Vue.js/Quasar 监听浏览器关闭上报离线状态实现方案

浏览器没有能100%覆盖所有场景的关闭事件钩子,组合原生事件+专用上报API+后端兜底可以覆盖绝大多数常规使用场景,具体实现如下:

核心事件选型

不要用老旧的unload事件,现代浏览器会强制拦截该事件内的异步请求,上报成功率极低,优先组合以下三个事件:

  • beforeunload:关闭标签页、关闭浏览器、主动刷新、跳转外站时触发,是最贴近页面关闭时机的钩子
  • pagehide:现代浏览器标准的页面卸载事件,移动端兼容性优于beforeunload
  • visibilitychange:兜底事件,覆盖页面切后台、最小化、移动端浏览器直接滑掉进程的部分场景

上报请求注意事项

普通的axios/fetch异步请求会在页面卸载时被浏览器直接终止,必须用浏览器专门为卸载场景设计的navigator.sendBeacon()接口发请求:

  • 该接口会将请求加入浏览器持久化任务队列,即使页面立即关闭也会保证请求发出
  • 请求默认异步发送,不会阻塞页面关闭/跳转,无用户体验损耗
  • 除了极个别年代久远的浏览器,全球98%以上的用户环境都支持该接口,无需额外兼容

框架内具体实现

Quasar 框架实现

在src/boot目录下新建全局状态监听的boot文件,全局绑定事件即可,无需在单个业务组件重复绑定:

// src/boot/user-presence.js
import { boot } from 'quasar/wrappers'

export default boot(() => {
  const reportOffline = () => {
    // 替换为自身业务需要的上报字段
    const payload = JSON.stringify({
      userId: localStorage.getItem('currentUid'),
      status: 'offline',
      reportTime: Date.now()
    })
    // 替换为自身后端的状态更新接口
    navigator.sendBeacon('/api/user/update-status', payload)
  }

  const handleBeforeUnload = (e) => {
    reportOffline()
    // 如需弹出关闭确认提示,放开下面两行注释即可
    // e.preventDefault()
    // e.returnValue = ''
  }
  const handlePageHide = () => reportOffline()
  const handleVisibilityChange = () => {
    if (document.visibilityState === 'hidden') reportOffline()
  }

  // 挂载全局监听
  window.addEventListener('beforeunload', handleBeforeUnload)
  window.addEventListener('pagehide', handlePageHide)
  document.addEventListener('visibilitychange', handleVisibilityChange)
})

写完记得在quasar.config.js的boot配置里加入这个新建的文件即可生效。

纯Vue.js 实现

直接在根组件App.vue的生命周期内绑定/解绑事件,避免内存泄漏:

<script setup>
import { onMounted, onUnmounted } from 'vue'

const reportOffline = () => {
  const payload = JSON.stringify({
    userId: localStorage.getItem('currentUid'),
    status: 'offline',
    reportTime: Date.now()
  })
  navigator.sendBeacon('/api/user/update-status', payload)
}

const handleBeforeUnload = (e) => {
  reportOffline()
  // 如需关闭确认提示放开下面注释
  // e.preventDefault()
  // e.returnValue = ''
}
const handlePageHide = () => reportOffline()
const handleVisibilityChange = () => {
  if (document.visibilityState === 'hidden') reportOffline()
}

onMounted(() => {
  window.addEventListener('beforeunload', handleBeforeUnload)
  window.addEventListener('pagehide', handlePageHide)
  document.addEventListener('visibilitychange', handleVisibilityChange)
})

onUnmounted(() => {
  window.removeEventListener('beforeunload', handleBeforeUnload)
  window.removeEventListener('pagehide', handlePageHide)
  document.removeEventListener('visibilitychange', handleVisibilityChange)
})
</script>

必做兜底方案

没有任何前端监听方案能覆盖极端异常场景:比如用户直接拔电源、浏览器崩溃、断网时事件根本不会触发,必须配合后端逻辑保证状态一致:

  • 加心跳机制:前端每30-60秒向后端发一次心跳请求,后端连续2个周期没收到心跳就自动将对应用户置为离线
  • 如果项目用了Websocket,直接监听Websocket的断连事件更新用户状态,可靠性远高于前端页面卸载事件

前端卸载事件上报只用来做即时状态更新,不要作为用户离线判断的唯一依据。


内容的提问来源于stack exchange,提问作者technobot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:15:51