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

如何实现Vue+JS+Shadcn项目中用户离开页面/标签页时的通知提醒?

实现方案(Vue + 原生API + Shadcn)

一、处理标签页切换/窗口最小化场景

利用Page Visibility API检测页面可见状态,搭配桌面通知API和Shadcn组件实现即时提醒,覆盖用户切换标签、最小化窗口的场景:

1. 核心代码实现

<script setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { Dialog, DialogContent, DialogDescription, DialogTitle } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'

const showReminder = ref(false)
const hasNotificationPermission = ref(false)

// 请求桌面通知权限
const requestPermission = async () => {
  const permission = await Notification.requestPermission()
  hasNotificationPermission.value = permission === 'granted'
}

// 监听页面可见性变化
const handleVisibilityChange = () => {
  if (document.hidden) {
    // 1. 显示Shadcn弹窗(用户切回页面时立即看到)
    showReminder.value = true

    // 2. 发送桌面通知(用户在其他标签/桌面也能收到提醒)
    if (hasNotificationPermission.value) {
      new Notification('别离开呀!', {
        body: '你的操作还没完成,快回来吧~',
        icon: '/your-icon.png' // 可选,设置通知图标
      })
    }
  }
}

onMounted(() => {
  requestPermission()
  document.addEventListener('visibilitychange', handleVisibilityChange)
})

onUnmounted(() => {
  document.removeEventListener('visibilitychange', handleVisibilityChange)
})
</script>

<template>
  <Dialog :open="showReminder" :on-open-change="(open) => showReminder = open">
    <DialogContent>
      <DialogTitle>请不要离开</DialogTitle>
      <DialogDescription>
        你还有未完成的操作,是否继续留在当前页面?
      </DialogDescription>
      <div class="flex justify-end gap-2 mt-4">
        <Button @click="showReminder = false">我知道了</Button>
      </div>
    </DialogContent>
  </Dialog>
</template>

关键说明

  • document.hidden会在页面切换到其他标签、窗口最小化时变为true,精准触发提醒逻辑
  • 桌面通知需要用户提前授权,本地开发(localhost)无需HTTPS,线上环境必须使用HTTPS
  • Shadcn的Dialog组件提供了美观的页面内提醒,用户切回页面时能第一时间感知

二、处理浏览器关闭/页面刷新场景

使用beforeunload事件拦截页面卸载,触发浏览器原生确认框,覆盖用户关闭浏览器、刷新页面、跳转其他域名的场景:

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

const handleBeforeUnload = (e) => {
  // 阻止默认行为,触发浏览器确认框
  e.preventDefault()
  // Chrome等浏览器需要设置returnValue才能生效
  e.returnValue = ''
}

onMounted(() => {
  window.addEventListener('beforeunload', handleBeforeUnload)
})

onUnmounted(() => {
  window.removeEventListener('beforeunload', handleBeforeUnload)
})
</script>

关键说明

  • 出于安全限制,无法自定义确认框的内容,只能使用浏览器默认的提示文案
  • 仅在用户主动触发页面卸载时生效,不会干扰正常的页面跳转(同域名跳转可根据需求排除)

三、增强体验:标题闪烁提醒

针对用户停留在其他标签页的场景,可通过修改页面标题实现闪烁效果,进一步吸引用户注意:

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

const originalTitle = ref(document.title)
let titleToggleTimer = null

const toggleTitle = () => {
  document.title = document.title === originalTitle.value ? '⚠️ 请返回页面!' : originalTitle.value
}

const handleVisibilityChange = () => {
  if (document.hidden) {
    titleToggleTimer = setInterval(toggleTitle, 1000)
  } else {
    clearInterval(titleToggleTimer)
    document.title = originalTitle.value
  }
}

onMounted(() => {
  document.addEventListener('visibilitychange', handleVisibilityChange)
})

onUnmounted(() => {
  document.removeEventListener('visibilitychange', handleVisibilityChange)
  clearInterval(titleToggleTimer)
})
</script>

注意事项

  • 避免滥用提醒逻辑,建议仅在用户有未保存表单、未完成操作等场景下触发,防止打扰用户
  • 桌面通知权限需要用户主动授权,可在页面加载时或用户开始操作后请求授权

内容的提问来源于stack exchange,提问作者LAU WEI FENG JAMESZ _

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:03:14