notification api 必须先调用 requestpermission() 获取用户授权,且需绑定在用户手势事件中;chrome 要求 https(localhost 除外),safari 需系统级授权且不支持 icon/badge;权限初始为 'default',拒绝后不再弹窗;icon 需绝对 https 路径,tag 可去重;移动端转系统通知,前端无法关闭已发出通知。

Notification API 需要用户授权才能触发
浏览器不会自动弹出通知,必须先调用 Notification.requestPermission() 获取用户明确授权。如果跳过这步直接调用 new Notification(),控制台会报错 DOMException: The user has blocked notifications 或静默失败。
常见错误是把权限请求放在页面加载后立刻执行,导致被浏览器拦截(尤其 Chrome 会在非用户手势上下文中拒绝)。正确做法是绑定到用户点击等交互事件中:
button.addEventListener('click', () => {
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
new Notification('你好', { body: '这是一条桌面通知' });
}
});
});
Chrome 和 Safari 对 Notification 权限策略差异大
Chrome 要求页面协议为 https://(localhost 除外),HTTP 页面调用 Notification.requestPermission() 会直接返回 'denied';Safari 还额外要求用户在「系统偏好设置 → 通知」中允许 Safari 发送通知,且其 API 不支持 icon 和 badge 字段(传入会被忽略)。
判断是否可用时不能只看 typeof Notification !== 'undefined',还要检查权限状态:
if ('Notification' in window && Notification.permission !== 'denied') {
// 可尝试请求或发送
}
-
Notification.permission初始值是'default',不代表已授权 - 用户点“不允许”后,再次调用
requestPermission()不会再弹窗,需引导用户手动修改浏览器设置 - Firefox 支持所有字段但默认禁用通知,需在
about:config中开启dom.webnotifications.enabled
new Notification() 的参数和兼容性陷阱
构造函数第二个参数是 options 对象,常用字段有 body、icon、image、tag。其中 icon 必须是 HTTPS 路径(Chrome 下 HTTP icon 会加载失败,通知无图标);tag 用于去重:相同 tag 的新通知会替换旧通知,而不是堆叠。
容易踩的坑:
- 传入相对路径
icon: '/img/icon.png'在单页应用路由(如/user/profile)下可能解析成/user/img/icon.png—— 建议用绝对路径或new URL('/img/icon.png', import.meta.url).href -
image字段仅 Firefox 支持,Chrome/Safari 忽略;不要依赖它做关键信息展示 - 移动端(Android Chrome)不显示桌面通知,而是转为系统通知栏消息,
body是唯一可靠内容区
通知关闭后无法再通过 JS 操作
new Notification() 返回的实例只有 onclick、onshow、onerror、onclose 四个事件钩子,没有 .close() 方法(那是 Service Worker 里 registration.getNotifications() 返回对象的方法)。想主动关闭只能在 Service Worker 环境中操作,纯前端页面无法干预已发出的通知。
所以设计逻辑时要注意:
- 不要假设能“撤回”一条通知 ——
tag替换是唯一可控的覆盖方式 -
onclick回调里window.focus()在部分浏览器(如 Safari)无效,需配合clients.openWindow()(仅 Service Worker 可用) - 通知本身不携带状态,如需关联业务数据,得靠
tag或自定义data字段(注意:data是任意 JS 值,但仅在事件回调中可用,不参与渲染)
真正难的不是调用 API,而是处理权限流转、跨浏览器行为差异和用户中断后的降级方案。比如当 permission === 'denied' 时,至少该提供一个内嵌的 toast 提示作为备选。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











