notification.permission检查必须在用户交互后触发,否则requestpermission会被静默拒绝;notificationclick事件监听必须注册在service worker中;shownotification的data字段是传参关键;跳转前须resolve clients.matchall()并聚焦已有tab。

Notification.permission 检查必须在用户交互后触发
浏览器禁止页面一加载就弹请求权限,否则 Notification.requestPermission() 会被静默拒绝或直接返回 "denied"。必须绑定在按钮点击、链接激活等明确的用户操作里。
常见错误现象:页面 onload 里调用 requestPermission → 控制台报 “Only secure contexts can request permission”,或者返回值始终是 "default" 但后续无法显示通知。
- 正确做法:用一个
<button onclick="requestNotify()">开启通知</button> - 调用前先判断
if (!("Notification" in window))防止老浏览器报错 - 权限状态为
"granted"才能调用new Notification(),"denied"就别再试了
notificationclick 事件监听必须注册在 Service Worker 里
HTML 页面 JS 中监听 notificationclick 是无效的 —— 浏览器只会在 Service Worker 的 self.addEventListener("notificationclick", ...) 中触发该事件。这是硬性限制,不是兼容性问题。
使用场景:用户点击通知时跳转到指定页面(比如订单详情页),即使当前浏览器没打开你的站点,也能唤起 Tab 并定位到目标 URL。
- Service Worker 文件(如
sw.js)中必须注册notificationclick监听器 - 事件回调里要用
clients.openWindow(url)跳转,不能用window.location.href(此时没有 window) - 注意:如果目标 URL 不在同源下,
openWindow可能被浏览器拦截,建议始终跳转到自己域名下的路径
showNotification 的 data 字段是传参关键
registration.showNotification(title, options) 的 options.data 是唯一可靠方式,把跳转所需参数(如 ID、类型)带进 notificationclick 事件中。不要依赖 tag 或 body 做逻辑判断。
性能与兼容性影响:data 支持任意可序列化值(字符串、对象、数字),Chrome/Firefox/Edge 均支持,Safari 对 data 的支持较晚(iOS 16.4+ / macOS 13.3+),若需兼容旧 Safari,得降级处理(比如拼接在 tag 里并加前缀校验)。
- 发送通知时写入:
data: { page: "order", id: "ORD-789" } - 在 SW 的
notificationclick回调中取:event.notification.data.page - 避免在
data里塞大对象,影响推送序列化开销
跳转前必须 resolve clients.matchAll() 再聚焦已有 Tab
用户点击通知时,常希望已打开的页面被聚焦而非重复开新 Tab。这需要在 notificationclick 里主动查找匹配 URL 的 client,并 client.focus();找不到才 openWindow。
容易踩的坑:直接 openWindow 导致每次点击都新建标签页;或没 await clients.matchAll() 就操作 client,导致 focus 失效。
- 必须用
await clients.matchAll({ type: "window", includeUncontrolled: true }) - 遍历结果,用
client.url.includes("order?id=ORD-789")或类似逻辑匹配目标页 - 匹配成功后
client.focus()并 return,避免继续执行 openWindow - 注意:
includeUncontrolled: true是为了捕获非 SW 控制的页面(比如刚打开还没注册 SW 的 Tab)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











