跳转到内容

通知 · API

通知的 actions 与 badge 选项

发布于 更新于

actions 给持久通知添加按钮,badge 提供完整通知放不下时操作系统显示的小型单色图片,例如 Android 状态栏。两者都是 ServiceWorkerRegistration.showNotification() 的 options 字典成员;在已发布的浏览器中,除了 Firefox 152 的 actions 之外都仅限 Chromium;两者都与 Badging API 设置的应用图标计数无关。

registration.showNotification(title, {
badge: '/icons/badge-96.png',
actions: [{ action: 'reply', title: '回复', icon: '/icons/reply.png' }],
})
Notification.maxActions

actions 只被 showNotification() 接受;向 new Notification() 传入非空数组会抛出 TypeError。Notification.maxActions 是静态 getter,返回引擎显示的按钮数量。支持情况:actions 在 Chrome 53、Edge 18、Firefox 152;badge 在 Chrome 53、Edge 18;Safari 两者都不支持(BCD api.Notification.actions、api.Notification.badge)。

成员 类型 含义
actions[].action string 在 notificationclick 中以 event.action 返回的标识符。必填。
actions[].title string 按钮文字。必填。
actions[].icon string(URL),可选 在绘制图标的平台(Android;Windows 不绘制)上显示在按钮上的图片。
actions[].navigate string(URL),可选 Safari 18.4:打开该 URL 而不触发 notificationclick。Chromium 忽略它。
badge string(URL) 紧凑形态使用的图片。Android 会把它遮罩成剪影并以最高 4 倍密度显示,因此带透明背景的 96 × 96 像素单色 PNG 是可用的尺寸。

Chromium 最多显示 kMaximumActions = 2 个按钮(notification.mojom,chromium.googlesource.com),多余的不报错直接丢弃;Firefox 152 通过 maxActions 报告自己的上限。读取这个 getter,不要把 2 写死。

异常 触发条件
TypeError new Notification() 上的 actions 非空。Chromium:Actions are only supported for persistent notifications shown using ServiceWorkerRegistration.showNotification().
TypeError 某个 action 对象缺少 action 或 title,这两个是必填的字典成员。

不支持的选项不是异常:Firefox 152 之前的版本和 Safari 忽略 actions,Chromium 之外的所有引擎忽略 badge,通知只带正文显示。

actions 与 badge 在 Chrome 53(2016 年)一起发布,并随 Edge 转向 Chromium 到达 Edge;Firefox 在 152 加入了 actions 但仍忽略 badge;Safari 在 macOS 和 iOS 上两者都不支持,通知按钮不属于其 Web 通知界面(BCD api.Notification.actions、api.Notification.badge)。在 Android 上 badge 显示在状态栏和锁屏上;在 Windows 和 macOS 上 Chromium 忽略 badge,因为操作系统没有紧凑形态的位置。

示例把页面侧的 showNotification() 调用与读取 event.action 的 Service Worker 处理函数配对。

Service Worker 读取 event.action。空字符串表示点的是通知主体,其他值是某个 action id。

// 页面
await registration.showNotification('Ada 发来新消息', {
body: '能把电话改到下午 3 点吗?',
badge: '/icons/badge-96.png',
tag: 'thread-42',
data: { threadId: 42 },
actions: [
{ action: 'reply', title: '回复' },
{ action: 'mute', title: '静音此会话' },
],
});
// Service Worker
self.addEventListener('notificationclick', (event) => {
event.notification.close();
const { threadId } = event.notification.data;
if (event.action === 'mute') {
event.waitUntil(fetch(`/api/threads/${threadId}/mute`, { method: 'POST' }));
} else {
event.waitUntil(self.clients.openWindow(`/threads/${threadId}${event.action === 'reply' ? '#compose' : ''}`));
}
});

Chromium 的上限是两个,所以按「主要操作、破坏性操作」的顺序放;第三个按钮会被丢弃。

badge 以剪影方式绘制:每个不透明像素都变成白色(或系统强调色),带内部细节的 logo 会变成一团。导出一个 96 × 96 像素、透明背景的单色图形。

await registration.showNotification('下载完成', {
body: 'report-2026-q3.pdf',
icon: '/icons/icon-192.png', // 全彩,显示在文字旁
badge: '/icons/badge-96.png', // 单色,显示在状态栏
});

icon 与 badge 服务于不同的位置,两者都值得设置;只有 icon 的通知在 Android 状态栏里显示的是浏览器自己的图标。

检测选项并在不支持处省略它们

Section titled “检测选项并在不支持处省略它们”

支持这些选项的地方,它们是 Notification.prototype 的属性。按条件构建选项对象,同一个调用就能在 Safari 和 Firefox 里工作。

function notificationOptions(base, buttons) {
if (!('Notification' in window)) return null; // 完全没有通知
const options = { ...base };
if ('badge' in Notification.prototype) options.badge = '/icons/badge-96.png';
if ('actions' in Notification.prototype && Notification.maxActions > 0) {
options.actions = buttons.slice(0, Notification.maxActions);
}
return options;
}

按 maxActions 截取保留的是前几个按钮,而不是让引擎随意丢掉后面的;当数组顺序是「主要、次要、破坏性」时这一点很重要。

规范

规范状态
无。