☰
VueUse `useWebNotification` 实战指南:在 AIRI 的 Vue 应用中构建响应式桌面通知
2026/10/16 3:50:10 网站建设 项目流程
  • 人工智能
  • AI Agent
  • MCP 服务
  • 工具调用
  • GUI 自动化
  • 语音
  • 数字人
  • 交互助手

【免费下载链接】airi

💖🧸 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器,目标是接近 Neuro-sama 的高度;支持实时语音聊天、Minecraft 和 Factorio 游玩,支持 Web / macOS / Windows。

项目地址:https://gitcode.com/moeru-ai/airi
点击查看免费下载

导读

useWebNotification是 VueUse 提供的一个响应式封装,它把浏览器原生 Notification API(Web Notifications API)变成了可直接用于 Vue 组合式 API 的 composable,让你可以用最少的样板代码完成「请求权限 → 展示通知 → 响应通知事件」的完整链路。在 Moeru AI AIRI 这类同时运行于 Web / macOS / Windows 的自托管 AI 伴侣项目中,它非常适合用于渲染进程中的结果反馈、任务完成提醒等场景。读完本文,你将掌握useWebNotification的全部选项、事件钩子与类型签名,并能对照仓库中 Electron 与 Capacitor 两套通知实现,判断在不同运行环境下该如何选择通知方案。

本文的关联参考文档位于 .agents/skills/vueuse-functions/references/useWebNotification.md,它是仓库内vueuse-functions技能(见 .agents/skills/vueuse-functions/SKILL.md)为 VueUse 各函数维护的标准参考之一,其中将useWebNotification归类于Browser(浏览器)类别,调用规则为AUTO(即:只要适用就应优先使用,而不是手写原生 API)。

核心用法:一条命令拉起完整通知链路

useWebNotification的名字里就带着 "Reactive"——它把Notification、权限状态、事件回调全部接入 Vue 的响应式系统。最小示例:

import { useWebNotification } from '@vueuse/core' const { isSupported, notification, permissionGranted, show, close, onClick, onShow, onError, onClose, } = useWebNotification({ title: 'Hello, VueUse world!', dir: 'auto', lang: 'en', renotify: true, tag: 'test', }) if (isSupported.value && permissionGranted.value) show()

这段代码来自原参考文档,它演示了三个关键点:

  1. isSupported先行判断:并非所有浏览器/运行环境都实现了 Notification API(例如部分隐私模式或旧版 WebView),isSupported作为Supportable的响应式标识,用于在展示前做能力探测;
  2. permissionGranted响应式权限状态:不需要手动调用Notification.permission,权限变化会自动反映到该ShallowRef上;
  3. show()直接展示:在权限已授予的前提下,调用show()即可弹出通知,无需手动new Notification(...)。

提示(原文档 Tip):应用能够发送通知的前提是用户已经授予权限;同时用户操作系统层面的通知设置也可能阻止预期行为(例如 Windows 的「专注助手」、macOS 的「勿扰模式」)。因此即使permissionGranted为true,也不应假定通知一定可见。

事件钩子:onClick/onShow/onError/onClose

通知的生命周期事件(点击、展示、出错、关闭)在原生的Notification上是分散的事件回调,useWebNotification通过 VueUse 的createEventHook工具把它们统一成了可注册的钩子函数:

import { useWebNotification } from '@vueuse/core' const { onClick, onShow, onError, onClose } = useWebNotification() // ---cut--- onClick((evt: Event) => { // Do something with the notification on:click event... }) onShow((evt: Event) => { // Do something with the notification on:show event... }) onError((evt: Event) => { // Do something with the notification on:error event... }) onClose((evt: Event) => { // Do something with the notification on:close event... })

这里onClick((evt) => {...})的返回值是一个带有off()方法的取消注册句柄,这一接口正是createEventHook的EventHookOn<T>类型(详见 .agents/skills/vueuse-functions/references/createEventHook.md 中的类型声明)。也就是说,useWebNotification底层复用了createEventHook的「on/off/trigger/clear」机制,事件监听可以随时注销,避免组件卸载后回调泄漏。

参数全解:WebNotificationOptions与UseWebNotificationOptions

以下两个接口是useWebNotification的全部可配置项,字段与默认值均来自原文档的类型声明:

WebNotificationOptions(对应原生Notification构造参数)

参数类型默认值说明
titlestring''通知的标题(只读属性,展示在通知头部)
bodystring''通知的正文文本
dir"auto" \| "ltr" \| "rtl"''通知文本方向,auto跟随语言环境,ltr/rtl强制左/右对齐
langstring''(DOMString)通知的语言代码,如'en'、'zh-CN'
tagstring''通知的 ID 标签,同tag的新通知会替换旧通知,用于去重与更新场景
iconstring''作为通知图标的图片 URL
renotifybooleanfalse当新通知替换旧通知时,是否再次提醒用户(发出声音/振动)
requireInteractionbooleanfalse通知是否保持激活直到用户点击或关闭,而非自动消失
silentbooleanfalse是否静默,不发出声音和振动(与设备设置无关)
vibratenumber[]—振动模式数组,按 Vibration API 规范作用于带振动硬件的设备(如移动端)

UseWebNotificationOptions(组合式配置)

export interface UseWebNotificationOptions extends ConfigurableWindow, WebNotificationOptions { /** * Request for permissions onMounted if it's not granted. * Can be disabled and calling `ensurePermissions` to grant afterwords. * * @default true */ requestPermissions?: boolean }
  • 继承ConfigurableWindow:可通过window选项注入自定义的window对象,方便 SSR、测试或 iframe 等场景;
  • requestPermissions(默认true):在组件挂载时若权限尚未授予,自动调用权限申请。如果你想推迟到某个用户交互(如点击按钮)时再申请,可将其设为false,之后手动调用返回的ensurePermissions()。

返回值全解:UseWebNotificationReturn

export interface UseWebNotificationReturn extends Supportable { notification: ShallowRef<Notification | null> ensurePermissions: () => Promise<boolean | undefined> permissionGranted: ShallowRef<boolean> show: ( overrides?: WebNotificationOptions, ) => Promise<Notification | undefined> close: () => void onClick: EventHookOn<Event> onShow: EventHookOn<Event> onError: EventHookOn<Event> onClose: EventHookOn<Event> }
返回值类型说明
isSupported继承自Supportable当前环境是否支持 Notification API
notificationShallowRef<Notification \| null>最近一次展示的Notification实例引用,未展示时为null
permissionGrantedShallowRef<boolean>权限是否已授予,响应式跟踪
ensurePermissions() => Promise<boolean \| undefined>手动申请权限;返回是否授予,未执行申请时返回undefined
show(overrides?: WebNotificationOptions) => Promise<Notification \| undefined>展示通知;可在调用时覆盖部分选项(如临时换body),返回新通知实例
close() => void关闭当前通知
onClick/onShow/onError/onCloseEventHookOn<Event>四个生命周期事件钩子,注册回调并返回{ off }取消句柄

值得注意show(overrides)的设计:通知参数既可以在初始化时统一声明,也可以在展示时按需覆盖。例如初始化设置统一的title与tag,调用show({ body: '新消息' })只覆盖正文,这比每次手动new Notification(...)更契合响应式场景。

结合 AIRI 仓库:同一项目的三种通知实现

AIRI 是一个同时面向 Web、移动端(Capacitor)与桌面端(Electron)的跨端项目,通知能力在不同运行环境下有各自的实现路径,理解这些边界有助于判断useWebNotification的适用场景:

1. 浏览器环境:useWebNotification(本文主角)

@vueuse/core是仓库各应用与包的公共依赖,例如 apps/stage-pocket/package.json 中声明了"@vueuse/core": "catalog:",apps/stage-tamagotchi/package.json 同样如此。在纯 Web 渲染层,useWebNotification是标准的「前端响应式通知」方案——它的底层就是浏览器window.Notification,因此只能在渲染进程 / 浏览器标签页中使用。

2. Electron 桌面端:主进程Notification+ IPC

在桌面端apps/stage-tamagotchi中,通知由Electron 主进程的Notification(Node 侧 API)承担,而不是浏览器 API。以 Spotlight 快速问答窗口为例:

  • 渲染进程在 apps/stage-tamagotchi/src/renderer/pages/spotlight.vue 中,问答完成后通过electronSpotlightShowResultNotification这个 eventa 事件(见 apps/stage-tamagotchi/src/shared/eventa/index.ts)把结果正文交给主进程;
  • 主进程在 apps/stage-tamagotchi/src/main/windows/spotlight/index.ts 的showNotification()中创建new Notification({ title: 'AIRI', body, ... })并监听close/failed/click事件。

这段实现里有一个值得借鉴的工程细节(源码注释中明确说明):Electron 可能会在构造作用域返回后将Notification对象 GC 回收,导致click处理器静默失效,因此代码用resultNotifications = new Set<Notification>()持有强引用,直到通知被close、failed或click后才释放。这一经验同样适用于浏览器端:如果你脱离useWebNotification手写new Notification(),也要警惕实例被垃圾回收导致事件丢失。

3. Capacitor 移动端:LocalNotifications插件

在移动端应用apps/stage-pocket中,通知走的是 Capacitor 原生插件@capacitor/local-notifications:

  • 开发工具页 apps/stage-pocket/src/pages/devtools/notifications.vue 演示了完整的权限与调度流程:checkPermissions()→(未授予时)requestPermissions()→schedule({ notifications: [...] }),支持id、title、body和schedule.at延迟调度;
  • 权限面板 apps/stage-pocket/src/components/permissions/permissions-panel.vue 还展示了更完善的权限治理:被拒绝时通过capacitor-native-settings跳转系统设置(optionAndroid: AndroidSettings.AppNotification、optionIOS: IOSSettings.AppNotification),iOS 上还可以走requestPermission的写回逻辑。

也就是说,如果通知的目标设备是 Android/iOS,应使用LocalNotifications(原生通知、可持久调度);如果是桌面/浏览器渲染层,Web 端的useWebNotification与 Electron 主进程Notification才是对应方案。useWebNotification的isSupported在这些受限环境下会如实返回false,这也是它作为「能力探测 + 响应式封装」的价值所在。

典型实战模式

把上述知识点组合起来,一个符合仓库编码风格(组合式优先、事件钩子驱动)的完整用法如下:

import { useWebNotification } from '@vueuse/core' const { isSupported, permissionGranted, ensurePermissions, show, close, onClick, onShow, onError, onClose, } = useWebNotification({ title: 'AIRI', dir: 'auto', lang: navigator.language ?? 'zh-CN', tag: 'ai-result', renotify: false, requireInteraction: false, requestPermissions: false, // 延迟到用户交互时再申请 }) // 用户点击通知 → 聚焦聊天窗口 onClick(() => { // 处理点击跳转 }) onShow((evt) => { // 展示成功后的埋点/日志 }) onError((evt) => { // 展示失败时降级为应用内 toast }) async function onUserClickNotifyButton() { if (!isSupported.value) return if (!permissionGranted.value) { const granted = await ensurePermissions() if (!granted) return // 引导用户到系统设置开启通知 } await show({ body: '结果已就绪' }) } // 组件卸载时自动释放事件监听(createEventHook 的 off 语义) onScopeDispose(close)

要点回顾:

  • 用requestPermissions: false+ensurePermissions()把权限申请绑定到明确的用户手势上,符合浏览器对通知权限的「须由用户触发」约束,也避免页面加载即弹权限框的糟糕体验;
  • show(overrides)只覆盖本次需要的字段;
  • 事件钩子通过createEventHook提供off()能力,配合onScopeDispose可确保组件销毁时资源被正确清理。

小结

useWebNotification把浏览器 Notification API 的权限、展示、事件三条链路全部响应式化,是 Vue 应用中「浏览器桌面通知」的标准实现。结合 AIRI 仓库可以看到完整的通知能力矩阵:Web 渲染层用useWebNotification,Electron 桌面端用主进程Notification并通过 IPC 转发(需注意 GC 导致的事件丢失问题),移动端则用 CapacitorLocalNotifications。掌握isSupported能力探测、permissionGranted/ensurePermissions权限治理、show(overrides)覆盖式展示与四个事件钩子,你就能在不同运行环境下写出既简洁又健壮的通知逻辑。

  • 人工智能
  • AI Agent
  • MCP 服务
  • 工具调用
  • GUI 自动化
  • 语音
  • 数字人
  • 交互助手

【免费下载链接】airi

💖🧸 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器,目标是接近 Neuro-sama 的高度;支持实时语音聊天、Minecraft 和 Factorio 游玩,支持 Web / macOS / Windows。

项目地址:https://gitcode.com/moeru-ai/airi
点击查看免费下载
上一篇:【亲测免费】 VBA-JSON 开源项目指南及问题解决方案
下一篇:【免费下载】 VBA-JSON: 在VBA中轻松处理JSON数据

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询