通知的 actions 与 badge 选项
发布于 更新于
一句话: actions 最多可以为一条通知添加 Notification.maxActions 个可点击按钮;badge
是一个独立的选项——根据 MDN,它是操作系统在 “there is not enough space to display the
notification itself”(没有足够空间展示完整通知)时展示的一张小图片,例如 Android 的通知栏。
这两者都是 Service Worker 驱动通知上的选项,并不是应用图标的 Badging API。
actions—— 根据 MDN,这是一个只读数组,其元素为对象,包含action(标识字符串)、title(按钮文案)、可选的iconURL,以及可选的navigateURL。根据 MDN,“browsers typically limit the maximum number of actions they will display”(浏览器通常会限制展示的 按钮数量),该上限通过静态属性Notification.maxActions暴露。badge—— 根据 MDN,它是 “a string containing the URL of an image”(一个包含图片 URL 的字符串),在空间不足时替代完整通知展示;MDN 针对 Android 的指引建议尺寸 “about 96 by 96 px”(约 96×96 像素),并说明该图片 “will be automatically masked”(会被自动进行遮罩处理)。
const permission = await Notification.requestPermission();if (permission === 'granted') { const registration = await navigator.serviceWorker.ready; await registration.showNotification('New message', { body: 'Ada sent you a message.', badge: '/icons/badge-96.png', actions: [ { action: 'reply', title: 'Reply' }, { action: 'dismiss', title: 'Dismiss' }, ], });}持久化通知前提
Section titled “持久化通知前提”根据 MDN,actions 仅 “only for persistent notifications”(适用于持久化通知)——即通过
ServiceWorkerRegistration.showNotification() 展示的通知——而不适用于直接 new Notification()。MDN 指出,向 Notification() 构造函数传入非 null 的 actions 选项会
“throws a TypeError”(抛出 TypeError)。
点击某个操作按钮后会发生什么,取决于该 action 是否设置了 navigate URL。根据 MDN 的
actions 文档,如果设置了 navigate,浏览器会直接导航到该 URL,并且不会派发
notificationclick 事件。只有当某个 action 没有设置 navigate URL 时,点击才会到达
Service Worker 的 notificationclick 事件,此时 event.action 中保存着被点击按钮的
action 字符串。
根据上面引用的 browser-compat-data:
| 浏览器 | actions |
badge |
|---|---|---|
| Chrome(桌面版) | 支持,自 53 版起 | 支持,自 53 版起 |
| Edge(桌面版) | 支持,自 18 版起 | 支持,自 18 版起 |
| Opera(桌面版) | 支持,自 39 版起 | 支持,自 39 版起 |
| Firefox(桌面版) | 支持,自 152 版起 | 不支持 |
| Safari | 不支持 | 不支持 |
根据 MDN,这两个选项都要求安全上下文。
如何在运行时检测
Section titled “如何在运行时检测”function canShowActionsAndBadge() { if (!('serviceWorker' in navigator) || !('Notification' in window)) { return { actions: false, badge: false }; // 这里完全不具备持久化通知能力 } return { actions: 'actions' in Notification.prototype, badge: 'badge' in Notification.prototype, };}
async function notifyNewMessage(registration) { const { actions, badge } = canShowActionsAndBadge(); const options = { body: 'Ada sent you a message.' }; if (badge) { options.badge = '/icons/badge-96.png'; } if (actions) { options.actions = [ { action: 'reply', title: 'Reply' }, { action: 'dismiss', title: 'Dismiss' }, ]; } // 当不支持 actions/badge 时,这里会改为发送仅含正文的通知——上面这些选项 // 只是被省略,而不会导致报错。 await registration.showNotification('New message', options);}- 不要向
new Notification()传入actions选项——根据 MDN,在非持久化(非 Service Worker)通知上这样做会抛出TypeError。 - 使用
Notification.maxActions而不是硬编码按钮数量;不同浏览器的上限不同。 - 不要把
badge选项的小型通知栏图片与独立的应用图标 Badging API (navigator.setAppBadge()) 混淆——它们解决的是不同的问题。 - 对设置了
navigateURL 的 action,预期浏览器会直接导航,而不会触发notificationclick事件;只有未设置navigate的 action 才会到达 Service Worker 的notificationclick事件,此时才在其中读取event.action。 - 依赖
actions前先确认上方的支持情况表——尤其是 Firefox;两个选项在 Safari 上都不 受支持。
- Notifications API —— 这两个选项所依赖的 基础权限模型与“页面 vs Service Worker”区分。
- 应用图标徽章 —— 用于在已安装应用图标上设置数字的 独立 Badging API。