如何实现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 _
相关产品推荐
相关产品推荐

