跳转到内容

Notification 接口:构造并读取单条通知

发布于

一句话: Notification 是单条已显示通知背后的接口——new Notification(title, options) 会从页面创建并立即显示一条通知,它的只读属性(title、body、data 等) 镜像了构造时传入的选项,并且会触发 click、close、error 事件供你监听。

if ('Notification' in window && Notification.permission === 'granted') {
const n = new Notification('订单已发货', {
body: '你的订单 #1234 正在配送途中。',
icon: '/icons/parcel.png',
tag: 'order-1234',
data: { orderId: '1234' },
});
n.addEventListener('click', () => {
window.focus();
n.close();
});
}

根据 MDN,构造前应先用 Notification.requestPermission() 获取权限——完整的权限流程见 Notifications API 一节。

  • body —— 显示在标题下方的次要文本。
  • icon —— 随通知显示的图标图片 URL。
  • tag —— 根据 MDN,通知的标识字符串;可与 renotify(要求非空 tag)配合,在 替换时再次提醒用户。
  • data —— 根据 MDN,任意结构化可克隆数据,通过 notification.data 读回。
  • requireInteraction —— 一个布尔值;根据 MDN,为 true 时通知会保持显示,直到 用户与其交互或将其关闭,而不是自动关闭。
  • click —— 用户点击通知时触发。
  • close —— 根据 MDN,用户关闭通知时触发。
  • error —— 通知显示出错时触发。

移动端的限制:改用 service worker

Section titled “移动端的限制:改用 service worker”

根据 MDN,直接调用 Notification() 构造函数在几乎所有移动端浏览器上都会抛出 TypeError,因为在移动端,页面脚本通常不会在后台运行——而这恰恰是通知本应触达的场景。 移动端安全的做法是注册一个 service worker,改为调用 ServiceWorkerRegistration.showNotification(),它支持相同的选项,还额外支持操作按钮,并 且无需打开页面即可工作:

async function notifyFromServiceWorker(title, options) {
if (
!('serviceWorker' in navigator) ||
!('Notification' in window) ||
Notification.permission !== 'granted'
) {
// 回退:不支持 service worker、没有 Notification API,或没有权限——
// 什么都不做,而不是调用构造函数冒着移动端 TypeError 的风险。
return;
}
const registration = await navigator.serviceWorker.ready;
if (typeof registration.showNotification !== 'function') {
// 回退:registration 已存在,但 showNotification 不可用——
// 没有移动端安全的 API 可用,不做更多操作。
return;
}
await registration.showNotification(title, options);
}

关于这一点如何应用于 push 投递的通知,参见 Web Push 与 iOS 与 Safari 上的 Web Push。

根据 MDN,Notification 属于有限可用,尚未进入 Baseline,因为它在部分主流浏览器中 表现并不一致——上文提到的移动端构造函数 TypeError 就是这种缺口的一个例子。更全面的 按平台权限与可用性说明参见 Notifications API。

  • 根据 MDN,构造前调用 Notification.requestPermission() 并检查是否为 granted。
  • 为相关通知设置 tag,需要在替换时再次提醒用户时配合 renotify。
  • 在 click 处理器中读取 notification.data,获取通知需要处理的负载。
  • 若不希望通知一直停留,点击时自行调用 notification.close()。
  • 在移动端,或任何需要 push 驱动通知的场景下,改用 ServiceWorkerRegistration.showNotification() 而非页面构造函数。