通知 notifications
本教程共 56 篇 · 第 31 篇 · 更新于 2026-08-13 · 约 7 分钟阅读
本节目标:学完你能用 chrome.notifications 弹出系统级通知,会选四种模板、配好图标和按钮,并能接住用户点击通知或按钮后的回调。
前面几章讲的界面组件都在浏览器里面:popup、侧边栏、右键菜单。但有些消息不能等用户回到浏览器才看到——下载完成了、定时提醒到了、后台任务出错了。这时候需要跳出浏览器,用操作系统的通知中心弹一条。
这就是 chrome.notifications 干的事。它不是网页里那种自绘的浮层,而是真正交给 Windows 通知中心、macOS 通知栏去显示的系统通知。
31-1 通知长什么样、什么脾气
一条通知通常包含四块:小图标、标题、正文、可选的按钮。系统会把它显示在屏幕角落,几秒后自动收进通知中心。
它的行为有几个特点你要提前知道,不然会觉得”我的通知怎么没了”:
- 它会自己消失。桌面上停留几秒就淡出,但仍留在系统通知中心里,用户可以回看。
- 它归系统管。用户在操作系统层面把 Chrome 的通知权限关了,你怎么调 API 都不会显示。
- 样式不能自定义。你只能选模板、填内容,具体长什么样由操作系统决定。
- 平台有差异。同一段代码在 Windows 和 macOS 上显示效果会略有不同。
Note通知是”打扰型”界面。用得好是贴心提醒,用滥了就是骚扰,用户会直接卸载。只在真正需要用户立刻知道的时候发。
31-2 先声明 notifications 权限
chrome.notifications 需要权限,清单里写上:
{
"manifest_version": 3,
"name": "通知示例",
"version": "1.0.0",
"permissions": ["notifications"],
"background": {
"service_worker": "service-worker.js"
},
"action": {
"default_popup": "popup.html"
},
"icons": {
"16": "images/icon-16.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
}
}
"notifications" 属于普通权限,不需要宿主权限,安装时用户会看到”显示通知”这条提示。
31-3 notifications.create 的最小写法
创建通知只有一个入口:chrome.notifications.create()。
await chrome.notifications.create(id, options);
id:可选,通知的唯一标识。传了它,之后就能用同一个 id 去更新或清除这条通知。不传,浏览器自动生成一个,通过回调或返回值拿到。options:通知内容对象,type、title、message、iconUrl是最基础的四项。
最常用的 basic 模板:
const options = {
type: 'basic',
iconUrl: 'images/icon-128.png',
title: '下载完成',
message: '报表已保存到下载目录。'
};
chrome.notifications.create('download-done', options);
这四个字段里,type、title、message、iconUrl 在创建时都是必填的。少一个就会报错,这是新手最常见的失败原因。
Tip通知代码最适合放在服务工作者(Service Worker)里。因为触发通知的往往是后台事件:定时器到点、下载结束、网络请求返回。popup 里也能调,但 popup 一关脚本就停了,不适合承载后台逻辑。
31-4 四种模板逐个看
type 字段决定通知的版式,一共四种。
basic:纯文字
最常规的一条,图标加标题加正文。
const options = {
type: 'basic',
title: 'Primary Title',
message: 'Primary message to display',
iconUrl: 'images/icon-128.png'
};
image:带预览图
在正文下面多一张大图,适合截图完成、图片处理完成这类场景。
const options = {
type: 'image',
title: '截图已保存',
message: '点击查看完整图片。',
iconUrl: 'images/icon-128.png',
imageUrl: 'images/preview.png'
};
imageUrl 是预览大图,iconUrl 仍然是左侧小图标,两者别搞混。
list:条目列表
一次要报多条内容时用它,比如”有 3 封新邮件”。
const options = {
type: 'list',
title: '你有 3 条新消息',
message: '点击查看全部',
iconUrl: 'images/icon-128.png',
items: [
{ title: 'Item1', message: 'This is item 1.' },
{ title: 'Item2', message: 'This is item 2.' },
{ title: 'Item3', message: 'This is item 3.' }
]
};
items 是数组,每项有自己的 title 和 message。
progress:进度条
progress 模板会显示一条进度条,取值范围是 0 到 100。
const options = {
type: 'progress',
title: '正在同步',
message: '已完成 42%',
iconUrl: 'images/icon-128.png',
progress: 42
};
Note平台差异在这里最明显:据社区经验,在 macOS 上进度可能不画成进度条,而是以百分比数值显示在通知标题里(此行为未见于官方文档,建议实测)。另外
imageUrl字段自 Chrome 59 起已被标记 deprecated,且在 Mac 上不可见,跨平台使用时别依赖它。
31-5 iconUrl 图标怎么给
iconUrl 是最容易出错的字段,三条规则就够:
- 必须是扩展包内的相对路径,比如
'images/icon-128.png'。写成外链远程图片在 Manifest V3 下不可靠。 - 尺寸给大一点。建议直接复用 128×128 的那张图标,系统会自己缩放。给 16×16 的小图在高分屏上会糊。
- 路径写错不会静默失败,
create()会抛错。调试时先去服务工作者的控制台看有没有报错。
需要绝对地址时可以用 chrome.runtime.getURL():
const options = {
type: 'basic',
iconUrl: chrome.runtime.getURL('images/icon-128.png'),
title: '提醒',
message: '喝水时间到了。'
};
chrome.notifications.create(options);
注意这次没传 id,只传了 options,这也是合法调用。
31-6 加按钮,接回调
通知可以带最多两个按钮,让用户直接在通知上做动作,不用回到浏览器。
chrome.notifications.create('water-reminder', {
type: 'basic',
iconUrl: 'images/icon-128.png',
title: '喝水提醒',
message: '已经一小时没喝水了。',
buttons: [{ title: '我喝了' }, { title: '稍后提醒' }]
});
按钮点了要有反应,就得监听事件。通知相关有三个常用事件:
// 用户点击了通知主体
chrome.notifications.onClicked.addListener((notificationId) => {
chrome.tabs.create({ url: 'https://example.com/detail' });
chrome.notifications.clear(notificationId);
});
// 用户点击了通知上的按钮
chrome.notifications.onButtonClicked.addListener((notificationId, buttonIndex) => {
if (buttonIndex === 0) {
console.log('用户点了「我喝了」');
} else {
console.log('用户点了「稍后提醒」');
}
chrome.notifications.clear(notificationId);
});
// 通知被关闭(自动消失或用户手动关)
chrome.notifications.onClosed.addListener((notificationId, byUser) => {
console.log(notificationId, byUser ? '被用户关掉了' : '自动消失了');
});
buttonIndex 就是 buttons 数组的下标,第一个按钮是 0,第二个是 1。
除了按钮,options 里还有几个字段值得知道:
priority:优先级,取值 -2 到 2,数字越大越显眼、停留越久。默认 0 就够用,别一律拉满。requireInteraction:设为true时通知不自动消失,要等用户自己处理。只留给真正重要的事,比如任务失败需要确认。silent:设为true就静音弹出,不发提示音。高频低价值的通知建议开静音。contextMessage:一行灰色的补充说明,适合放来源或时间戳。
chrome.notifications.create('sync-failed', {
type: 'basic',
iconUrl: 'images/icon-128.png',
title: '同步失败',
message: '服务器没有响应,请稍后重试。',
contextMessage: '来自「我的同步工具」',
priority: 2,
requireInteraction: true
});
Warning事件监听器必须写在服务工作者的顶层,不能塞在某个函数里等以后再注册。后台是事件驱动、随时休眠的,只有顶层注册的监听器才能在休眠后被事件重新唤醒。这条规则在服务工作者那章讲过,通知这里同样适用。
31-7 更新、清除与查询
传了 id 的通知可以后续操作,这也是”传 id”最大的价值。
同步进度就是典型场景——不要每次都创建新通知,而是更新同一条:
const NOTIF_ID = 'sync-progress';
async function reportProgress(percent) {
await chrome.notifications.update(NOTIF_ID, {
progress: percent,
message: `已完成 ${percent}%`
});
}
任务结束后主动清掉:
await chrome.notifications.clear(NOTIF_ID);
想知道当前还有哪些通知在,用 getAll():
const all = await chrome.notifications.getAll();
console.log(Object.keys(all)); // 所有还活着的通知 id
getAll() 返回的是一个对象,key 是通知 id,不是数组,别直接当数组遍历。
31-8 小结与实践建议
回顾这一节的骨架:清单加 "notifications" 权限 → chrome.notifications.create(id, options) 填四件套(type / title / message / iconUrl)→ 按需选模板(basic / image / list / progress)→ 顶层注册 onClicked、onButtonClicked、onClosed 接住交互 → 用 id 做 update / clear / getAll。
再给三条实践建议。第一,重要通知带上按钮,让用户一步完成操作,别逼他打开浏览器再找入口。第二,同一件事复用同一个 id,避免通知刷屏。第三,做好”通知被系统屏蔽”的兜底,重要状态在 popup 或侧边栏里也要能看到。
下一节换个方向,我们讲 devtools 面板扩展——怎么给浏览器的开发者工具加一个属于你自己的标签页。