HTML5通知API(Notification API)允许网页向用户显示桌面通知,即使用户没有主动浏览该网页。这种机制对于需要向用户发送即时消息的Web应用(如邮件客户端、即时通讯工具、日历提醒等)特别有用。
11.4.1 基本概念
通知API的核心特点:
- 异步通知:不打断用户当前工作流程
- 跨标签页:即使浏览器最小化也能显示
- 权限控制:需要用户明确授权
- 自定义内容:可设置标题、正文、图标等
11.4.2 权限请求与检查
在显示通知前,必须获取用户授权:
// 检查当前权限状态
const checkNotificationPermission = () => {
if (!('Notification' in window)) {
console.log('当前浏览器不支持通知API');
return false;
}
return Notification.permission;
};
// 可能的权限状态:
// - "default":尚未请求
// - "granted":已授权
// - "denied":已拒绝
// 请求通知权限
const requestNotificationPermission = async () => {
if (checkNotificationPermission() === 'granted') {
return true;
}
const permission = await Notification.requestPermission();
return permission === 'granted';
};
// 使用示例
requestNotificationPermission().then(hasPermission => {
if (hasPermission) {
console.log('用户已授权通知');
} else {
console.log('用户拒绝了通知权限');
}
});
11.4.3 显示通知
基本通知示例:
function showBasicNotification() {
if (checkNotificationPermission() !== 'granted') return;
const notification = new Notification('新消息通知', {
body: '您有3条未读消息',
icon: '/path/to/icon.png',
image: '/path/to/preview-image.jpg' // 大图预览(部分浏览器支持)
});
// 点击通知时触发
notification.onclick = () => {
console.log('通知被点击');
window.focus(); // 激活浏览器窗口
notification.close(); // 关闭通知
};
// 自动关闭(4秒后)
setTimeout(() => notification.close(), 4000);
}
11.4.4 高级通知功能
1. 持久性通知(带操作按钮)
function showPersistentNotification() {
if (!('showActions' in Notification.prototype)) {
console.log('当前浏览器不支持通知操作按钮');
return;
}
const notification = new Notification('待办事项提醒', {
body: '下午3点有团队会议',
icon: '/images/calendar-icon.png',
actions: [
{ action: 'snooze', title: '稍后提醒' },
{ action: 'done', title: '标记完成' }
],
requireInteraction: true // 不会自动关闭
});
notification.onclick = (event) => {
if (event.action) {
switch (event.action) {
case 'snooze':
console.log('用户选择了稍后提醒');
break;
case 'done':
console.log('用户标记为已完成');
break;
default:
console.log('通知主体被点击');
}
}
notification.close();
};
}
2. 服务工作者中的通知(PWA)
在Service Worker中显示通知:
// service-worker.js
self.addEventListener('push', event => {
const data = event.data.json();
const options = {
body: data.body,
icon: 'icons/icon-192x192.png',
badge: 'icons/badge-72x72.png',
data: { url: data.url } // 附加数据
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
self.addEventListener('notificationclick', event => {
event.notification.close();
// 打开特定URL
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});
11.4.5 通知生命周期管理
// 创建通知
const notification = new Notification('系统更新', {
body: '新版本已准备好安装',
tag: 'system-update' // 相同tag的通知会替换
});
// 关闭单个通知
notification.close();
// 关闭所有通知
Notification.closeAll();
// 监听关闭事件
notification.onclose = () => {
console.log('通知已关闭');
};
11.4.6 最佳实践
- 适时请求权限:在用户与相关功能交互时请求(如点击"启用通知"按钮)
- 提供价值:确保通知内容对用户确实有用
- 频率控制:避免过度发送通知造成打扰
- 内容简洁:标题和正文要简明扼要
- 提供设置:允许用户自定义通知偏好
11.4.7 实际应用示例
聊天应用通知
let notification;
let unreadCount = 0;
function showChatNotification(sender, message) {
if (document.hasFocus()) return; // 窗口活跃时不显示
unreadCount++;
// 如果已有通知,更新它
if (notification) {
notification.close();
}
notification = new Notification(`${sender}发来消息`, {
body: unreadCount > 1 ?
`您有${unreadCount}条未读消息` :
message,
icon: '/images/chat-icon.png',
badge: '/images/chat-badge.png',
tag: 'chat-messages'
});
notification.onclick = () => {
window.focus();
unreadCount = 0;
};
}
// 当窗口获得焦点时重置计数
window.addEventListener('focus', () => {
unreadCount = 0;
if (notification) {
notification.close();
notification = null;
}
});
预约提醒
function scheduleAppointmentReminder(appointmentDate, title, description) {
const now = new Date();
const timeUntilAppointment = appointmentDate - now;
if (timeUntilAppointment <= 0) return;
// 提前15分钟提醒
setTimeout(() => {
if (Notification.permission === 'granted') {
const notification = new Notification(`即将到来: ${title}`, {
body: `您的预约将在15分钟后开始\n${description}`,
icon: '/images/calendar-notification.png',
vibrate: [200, 100, 200] // 振动模式(移动设备)
});
notification.onclick = () => {
window.location.href = '/calendar';
};
}
}, timeUntilAppointment - (15 * 60 * 1000));
}
11.4.8 浏览器兼容性
通知API的主要功能在现代浏览器中得到良好支持:
- Chrome 22+(完全支持)
- Firefox 22+(完全支持)
- Safari 7+(Mac OS X 10.9+)
- Edge 14+
- Opera 25+
移动端支持情况:
- Android Chrome 完全支持
- iOS Safari 部分支持(仅在PWA模式下)
11.4.9 安全与隐私考虑
- HTTPS要求:现代浏览器要求通知API必须在安全上下文(HTTPS)中使用
- 用户控制:用户可以在浏览器设置中随时更改通知权限
- 滥用防护:浏览器可能会限制频繁或滥用通知的网站
- 数据安全:通知内容应避免包含敏感信息
11.4.10 常见问题解决方案
问题1:通知不显示
- 检查权限状态是否为"granted"
- 确保在用户交互(如点击)后触发
- 验证是否在安全上下文(HTTPS)中
问题2:移动设备上不工作
- iOS上可能需要将应用添加到主屏幕(PWA)
- Android上可能需要服务工作者支持
问题3:用户忽略通知
- 优化通知内容和时机
- 提供自定义设置让用户选择接收哪些通知
通过合理使用通知API,可以显著提升Web应用的用户参与度和留存率,但需要平衡功能性和用户体验,避免造成通知疲劳。