跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端

浏览器桌面通知功能从零实现指南

浏览器通知功能允许网页在浏览器窗口外发送提醒,常用于消息通知和状态更新。实现核心在于处理三种权限状态:默认、允许和拒绝。必须确保在 HTTPS 或 localhost 环境下运行,并通过 Notification.requestPermission 获取用户授权。若用户拒绝,需引导其手动进入浏览器设置开启。代码中需注意处理 denied 状态下的跳转逻辑,利用 tag 属性避免通知堆积,并结合 Service Worker 实现离线通知能力。

乱七八糟发布于 2026/3/26更新于 2026/10/2689 浏览
浏览器桌面通知功能从零实现指南

浏览器桌面通知功能从零实现指南

作为前端开发者,你可能见过这样的场景:打开网页版聊天工具,即使把浏览器最小化,桌面也会弹出'新消息'提醒;或者某些网站的活动通知直接显示在电脑或手机桌面上。这种功能就是「浏览器桌面通知」。

今天我们就从零开始,搞懂它、学会用它,避免踩坑。

一、先搞懂 3 个基础问题

1. 什么是浏览器桌面通知?

简单说,就是网页能在浏览器窗口外面(比如电脑桌面、手机屏幕)给你发提醒。哪怕浏览器最小化、甚至页面切到后台,只要权限允许,都能收到通知,不用一直盯着网页。

2. 什么时候会用到它?

常见场景很贴近日常:

  • 网页版即时通讯的新消息提醒;
  • 工作系统的审批提醒、任务到期通知;
  • 电商网站的订单状态更新(比如'你的快递已发货');
  • 新闻或小说网站的订阅内容更新提醒。

3. 用起来难吗?有什么限制?

不难!核心就两步:先让用户同意开启通知(申请权限),再发送通知。 关键限制要记好(避免踩坑):

  • 必须在安全环境下用:网站要部署在 HTTPS 服务器上(本地开发用 localhost 可以正常测试,不用纠结 HTTPS);
  • 要用户主动同意:不能偷偷发通知,必须先让用户点击'允许'才行;
  • 大部分现代浏览器都支持:Chrome、Edge、Firefox、Safari(手机端也支持,部分需要特殊设置)。

二、核心概念:通知权限(最关键的一步)

浏览器为了保护用户,给通知加了'权限管理'——就像你家开门,必须经过主人同意,外人才能进。权限分 3 种状态,我们后续代码都要围绕这 3 种状态处理:

权限状态通俗理解我们能做什么
默认(default)用户还没选过'允许'或'拒绝'可以弹出弹窗,问用户要不要开启通知
允许(granted)用户同意开启通知了直接发通知,不用再问
拒绝(denied)用户之前点了'不允许'不能再弹请求弹窗了,只能引导用户手动去浏览器设置里改

提示:权限是'按网站保存'的,比如你允许了'网页版微信'的通知,不代表其他网站也能发,每个网站要单独申请。

三、从零实现:2 个核心功能

我们把功能拆成两部分:① 申请通知权限 ② 发送通知。下面的代码可以直接复制到你的 HTML 文件里运行,每一行都加了注释,初学者也能看懂。

第一步:准备 HTML 基础结构

先建一个简单的 HTML 文件,包含一个'开启通知'按钮和一个'发送测试通知'按钮,方便我们测试。这里我还加了一个引导按钮,专门处理用户拒绝后的情况。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    浏览器通知测试
    


    浏览器通知测试
    1. 开启通知权限
    2. 发送测试通知
    
    3. 重新开启通知权限(已拒绝用户点击)
    


<title>
</title>
<style>
/* 新增:给引导按钮加简单样式,默认隐藏 */ #guideReEnableBtn { margin-top: 10px; display: none; color: #fff; background-color: #ff7d00; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; } #guideReEnableBtn:hover { background-color: #e67100; }
</style>
</head>
<body>
<h1>
</h1>
<button id="requestPermissionBtn">
</button>
<button id="sendNoticeBtn" disabled>
</button>
<!-- 新增:拒绝后显示的引导按钮 -->
<button id="guideReEnableBtn">
</button>
<script>
// 这里放后续的 JS 代码
</script>
</body>
</html>

第二步:编写 JS 核心逻辑

接下来我们把 JS 逻辑填进去。这里有个细节要注意:当用户拒绝权限后,我们不能再次调用 requestPermission 弹窗,所以需要一个专门的引导函数来帮用户跳转到设置页。

// 1. 先获取页面上的所有按钮
const requestPermissionBtn = document.getElementById('requestPermissionBtn');
const sendNoticeBtn = document.getElementById('sendNoticeBtn');
const guideReEnableBtn = document.getElementById('guideReEnableBtn');

// 2. 定义一个变量,记录通知是否可用(方便后续判断)
let isNoticeEnabled = false;

// 3. 检测浏览器是否支持通知功能(避免在不支持的浏览器上报错)
function checkBrowserSupport() {
    if ('Notification' in window) {
        return true;
    } else {
        alert('你的浏览器不支持通知功能,请升级浏览器!');
        return false;
    }
}

// 新增:判断浏览器类型,返回对应通知设置页 URL(适配主流浏览器)
function getBrowserNoticeSettingsUrl() {
    const userAgent = navigator.userAgent;
    if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) {
        return 'chrome://settings/content/notifications';
    } else if (userAgent.includes('Edg')) {
        return 'edge://settings/content/notifications';
    } else if (userAgent.includes('Firefox')) {
        return 'about:preferences#privacy';
    } else {
        return '';
    }
}

// 新增:引导用户手动开启权限的函数
function guideReEnablePermission() {
    const settingsUrl = getBrowserNoticeSettingsUrl();
    
    if (settingsUrl) {
        const choice = confirm('请按以下步骤开启通知权限:\n\n1. 点击「确定」直接跳转到浏览器通知设置页\n2. 在设置页找到当前网站,将通知权限改为「允许」\n3. 刷新当前页面即可生效\n\n如果跳转失败,请手动操作:点击地址栏左侧小锁图标→找到「通知」→改为「允许』');
        if (choice) {
            try {
                window.open(settingsUrl, '_blank');
            } catch (error) {
                alert('跳转失败,请手动操作:点击地址栏左侧小锁图标→找到「通知」→改为「允许』');
            }
        }
    } else {
        alert('请按以下步骤手动开启通知权限:\n\n1. 点击浏览器地址栏左侧的「小锁图标」🔒\n2. 在弹出的菜单中找到「通知」选项\n3. 把「通知」状态从「阻止」改成「允许』\n4. 刷新页面后重新尝试');
    }
}

// 4. 申请通知权限(核心函数 1)
async function requestNoticePermission() {
    if (!checkBrowserSupport()) return;

    const permission = Notification.permission;
    
    if (permission === 'granted') {
        // 情况 1:用户已经允许过了
        isNoticeEnabled = true;
        alert('通知权限已开启!可以发送通知啦~');
        sendNoticeBtn.disabled = false;
        guideReEnableBtn.style.display = 'none';
    } else if (permission === 'denied') {
        // 情况 2:用户之前拒绝过,显示引导按钮
        guideReEnableBtn.style.display = 'block';
        sendNoticeBtn.disabled = true;
        alert('你之前拒绝了通知权限!请点击页面上的「重新开启通知权限」按钮,可选择直接跳转到设置页操作。');
    } else {
        // 情况 3:用户还没选过,弹出请求弹窗
        try {
            const userChoice = await Notification.requestPermission();
            if (userChoice === 'granted') {
                isNoticeEnabled = true;
                alert('你同意了通知权限!');
                sendNoticeBtn.disabled = false;
                guideReEnableBtn.style.display = 'none';
            } else {
                alert('你拒绝了通知权限,无法收到通知哦~\n如果后续想开启,可点击页面上的「重新开启通知权限」按钮。');
                guideReEnableBtn.style.display = 'block';
            }
        } catch (error) {
            console.error('申请权限失败:', error);
            alert('申请通知权限失败,请刷新页面重试');
        }
    }
}

// 5. 发送通知(核心函数 2)
function sendTestNotice() {
    if (!isNoticeEnabled) {
        alert('请先点击第一个按钮开启通知权限!');
        return;
    }

    const notice = new Notification('测试通知来啦!', {
        body: '恭喜你!成功发送了第一条浏览器通知~',
        icon: 'https://img.icons8.com/fluency/96/000000/notification.png',
        tag: 'test-notice',
        silent: false
    });

    // 点击通知时的操作:打开浏览器窗口,并关闭通知
    notice.onclick = function () {
        window.focus();
        notice.close();
    };

    // 3 秒后自动关闭通知(避免一直留在桌面)
    setTimeout(() => {
        notice.close();
    }, 3000);
}

// 绑定事件
requestPermissionBtn.addEventListener('click', requestNoticePermission);
sendNoticeBtn.addEventListener('click', sendTestNotice);
guideReEnableBtn.addEventListener('click', guideReEnablePermission);

第三步:测试步骤

  1. 把上面的 HTML 代码复制到一个文本文件里,把文件后缀改成 .html(比如 notice-test.html);
  2. 用 Chrome、Edge 等现代浏览器打开这个文件。注意:直接双击打开可能无法触发权限弹窗,建议使用 VS Code 的 Live Server 插件打开(地址栏显示 http://localhost:5500/...),这样能正常测试;
  3. 点击'1. 开启通知权限'按钮:第一次点击会弹出浏览器的权限弹窗,选择'允许';
  4. 允许后,'发送测试通知'按钮会变亮(从灰色变成可点击);
  5. 如果选择'拒绝',页面会显示「重新开启通知权限」按钮,点击后可选择直接跳转到浏览器设置页,或查看手动开启步骤;
  6. 点击'2. 发送测试通知'按钮:桌面会弹出通知,有标题、正文和图标,3 秒后自动关闭;点击通知会把浏览器调到前台。

四、常见问题排查

1. 点击'开启权限'没反应?

原因通常是浏览器不支持,或者打开方式不是 localhost/HTTPS。解决:用 Chrome/Edge 浏览器,确保使用 Live Server 打开(地址栏是 http://localhost 开头)。

2. 弹不出权限弹窗?

如果之前拒绝过权限,浏览器会持久化保存'拒绝'状态,后续无法通过代码再次弹出权限申请弹窗(这是浏览器的保护机制)。解决:使用页面中的「重新开启通知权限」按钮,点击后可选择直接跳转到浏览器设置页(适配 Chrome/Edge/Firefox),将通知权限从「阻止」改为「允许」,然后刷新页面。

3. 发送通知后,桌面没显示?

这通常不是浏览器的问题,而是系统通知被关闭了。

  • Windows:打开「设置→系统→通知和操作」,确保'通知'开启,并且浏览器的通知权限也开启;
  • Mac:打开「系统设置→通知」,找到对应的浏览器,开启'允许通知'。

4. 手机上测试没效果?

手机浏览器要求'通知请求必须由用户主动点击触发'(不能自动弹),且部分手机需要在系统设置里开启浏览器通知。解决:用手机浏览器打开文件(同样用 Live Server,确保手机和电脑在同一个网络),手动点击'开启权限'按钮,再发送通知。

五、进阶小技巧

  1. 自定义通知内容:发送通知时,把 new Notification('标题', {配置}) 里的标题、body 换成变量,就能实现'动态通知'(比如显示不同的消息内容);
  2. 避免通知堆积:用 tag 配置项,相同 tag 的通知会替换旧的(比如连续发两条'新消息'通知,只会显示最新的一条);
  3. 离线也能发通知:如果需要'页面关闭后还能收到通知',可以学习 Service Worker,搭配 Notification API 就能实现离线通知;
  4. 浏览器设置页快速跳转:通过判断浏览器类型,可实现点击按钮直接跳转到通知设置页,避免用户手动找路径(本文已实现该功能,适配主流浏览器)。

六、总结

浏览器通知功能的核心就是「先申请权限,再发送通知」。学习者只要记住这 2 步,再跟着上面的代码和步骤测试,就能快速上手。关键是要注意'安全环境(HTTPS/localhost)'和'用户主动授权'这两个点,避开常见坑就能顺利实现功能啦。

如果需要在实际项目中使用,只要把上面的测试代码稍作修改(比如替换图标、修改通知内容),就能直接用在自己的网页里!

目录

  1. 浏览器桌面通知功能从零实现指南
  2. 一、先搞懂 3 个基础问题
  3. 1. 什么是浏览器桌面通知?
  4. 2. 什么时候会用到它?
  5. 3. 用起来难吗?有什么限制?
  6. 二、核心概念:通知权限(最关键的一步)
  7. 三、从零实现:2 个核心功能
  8. 第一步:准备 HTML 基础结构
  9. 第二步:编写 JS 核心逻辑
  10. 第三步:测试步骤
  11. 四、常见问题排查
  12. 1. 点击“开启权限”没反应?
  13. 2. 弹不出权限弹窗?
  14. 3. 发送通知后,桌面没显示?
  15. 4. 手机上测试没效果?
  16. 五、进阶小技巧
  17. 六、总结

更多推荐文章

查看全部
  • WinSCP 安装、连接及高阶配置指南
  • AI 实践:工具函数调用详解
  • ComfyUI 云服务器部署实战与优化指南
  • Flutter 与 Web 混合开发实践:构建跨平台统一体验
  • VoxCPM-1.5-TTS-WEB-UI 基于镜像源快速部署指南
  • BMAD 开发实战:掌握 AI 辅助开发完整流程
  • AI 面试辅助工具即答侠技术架构与功能解析
  • 基于 1Panel 部署 OpenClaw 结合 Ollama 本地 AI 助理
  • 从 Stack Reconciler 到 Fiber:一份前端面试常考的 React 架构解读
  • Canvas 与 Web Audio API 实现交互式烟花动画
  • Web 开发者构建多模态 Agent 图像识别技能:JS+Python 全栈实践
  • 深度对比 vLLM、SGLang 与 llama.cpp:大模型推理引擎选型指南
  • 解决 VsCode 远程 SSH 环境下 Copilot Claude 模型与 Agent 异常问题
  • 转行 AI 产品经理:面试核心问题与准备指南
  • 豆包大模型定价进入“厘”时代,火山引擎方舟 2.0 发布
  • Agent 为何成为 AI 应用爆发点及企业盈利路径
  • 云边端一体化解析:AI 时代的基础设施核心
  • 数据结构:链表核心算法实战解析
  • Hookshot:轻量级 GitHub Webhook 处理工具
  • Obsidian Text Generator 插件完整指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online