H5的Notification特性 - Web的桌面通知功能
- 检查浏览器是否支持Notification
- 检查浏览器的通知权限(是否允许通知)
- 若权限不够则获取浏览器的通知权限
- 创建消息通知
- 展示消息通知
1通知权限 - Notification.permission
Notification.permission是一个静态方法,可以获取用户当前的通知权限状态,返回一个String,可以根据返回值判断用户是否授予了通知权限。返回值有三种情况:
default 用户还未被询问是否授权,所以通知不会被显示。
granted 表示之前已经询问过用户,并且用户已经授予了显示通知的权限。
denied 用户已经明确的拒绝了显示通知的权限。
当值为default或者denied时都不会显示通知消息,只有明确的被设置成granted才会显示通知消息

const permission = Notification.permission; if(permission === 'granted'){ console.log('已经授权通知,可以进行你的通知啦!'); }else if (Notification.permission === 'default') { console.log('用户还未选择同意/拒绝'); // 下一步请求用户授权 } else { console.log('用户曾经拒绝授权,不能显示通知'); }
2 请求权限 - Notification.requestPermission(CALLBACK)
应用发送通知之前必须要取得发送通知的权限,才能成功进行通知。Notification.requestPermission(CALLBACK)是请求获取权限的方法(有点类似javascript的confirm弹窗窗),允许传入一个回调,回调会返回用户选择的何种权限,返回两个值,granted代表允许,denied代表拒绝。并且Notification.requestPermission()支持then方式的链式调用,也就意味着可以异步调用它。
当Notification.permission为default的时候,我们需要使用Notification.requestPermission()来请求用户权限。
Notification.requestPermission()基于promise语法,then的回调函数参数是用户权限的状态Notification.permission的值。

//方式一,老版是回调函数机制 Notification.requestPermission(function (permission) { if (permission === 'granted') { console.log('用户同意授权'); // 随时可以显示通知 } else if (permission === 'default') { console.log('用户关闭授权,可以再次请求授权'); } else { console.log('用户拒绝授权,不能显示通知'); } }); //方式二,通过then回调,两种方式是等价的 Notification.requestPermission().then(function (permission) { if (permission === 'granted') { console.log('用户同意授权'); // 随时可以显示通知 } else if (permission === 'default') { console.log('用户关闭授权,可以再次请求授权'); } else { console.log('用户拒绝授权,不能显示通知'); } });
3 创建通知 - new Notification(TITLE, OPTIONS)
当Notification.permission为granted时,请求到用户权限之后,不必立即发送通知,可以在任意时刻,以任意形式来发送通知。new Notification(TITLE, OPTIONS)方法创建可以创建一个通知实例,允许参入参数两个参数TITLE和OPTIONS。注意默认情况下(实际可以通过OPTIONS中的timestamp参数控制)一旦通知实例被创建出来,它会立即被显示出来

var options = {}; // 传空配置 var title = '消息标题'; var notification = new Notification(title, options) // 显示通知
TITLE参数 OPTIONS
是非必须参数,必须为一个对象,它包含: ps: 部分参数在某些浏览器可能会不生效,建议使用最新版的谷歌浏览器。以下某些内容从Notification-MDN-EN结合谷歌翻译得来,

{ //通知显示正文。非必须,默认为空 body: '你的好友XX上线了!', //通知显示正文的图片地址。非必须,默认为空 image: 'imgae url', //通知左侧图标。非必须,默认为空 icon: 'imgae url', //通知的分类标记(ID)。非必须,默认为空 tag: 'test', //通知相关联的数据,通常用于方法的回调,传参。非必须,默认为空 data: '可以是任意数据类型', //通知显示延迟的时间。非必须,默认通知实例创建完成就显示 timestamp: '', //通知主体内容的水平展示顺序,有点类似direction属性。非必须,默认值是auto, 可以是ltr或rtl dir: 'auto', //当没有足够的空间来显示通知本身时,用于表示通知的图像的URL。非必须,默认为空 badge: 'xxx', //通知的语言。非必须默认为空 lang: '', //通知显示时,设备的振动模式。非必须,默认为空 vibrate: [200, 100, 200], //新通知出现是否覆盖旧的通知,覆盖(true)则永远只显示一条通知,不覆盖(false)则会多条通知重叠。非必须,默认为true renotify: true, //通知是否静音。非必须,默认为false,表示无声 silent: false, //通知声源文件地址。非必须,默认为空 sound: 'mp3', //是否不在屏幕上显示通知信息。非必须,默认为false表示要显示 noscreen: false, //指定通知是否应该粘滞性,即不容易被用户清理。非必须,默认false表示不具粘滞性 sticky: false, //指定通知是否保持活性,直到用户点击或关闭。非必须,默认为false requireInteraction: false }
其中,requireInteraction: 保持通知不自动关闭
默认值为false,通知会在三四秒之后自动关闭。
当设置为true
,并且当有超过两个通知(new Notification(title, options)
)时,会出现如下图的通知叠加状态
4.事件及事件钩子
生成通知,会返回一个实例,如下:
var instanceNotification = new Notification(title, options)
-
1.通知实例具有一个静态方法可以用来关闭通知
-
2.读取相关的配置
-
3.通知实例具有四个事件钩子,来跟踪通知当前的状态。
1 关闭通知
instanceNotification.close()
没有设置不自动关闭的话,chrome通知将会在4.5秒左右自动关闭通知,safari则是5秒钟(无法设置不自动关闭)。
notification没有定时控制通知多久后消失的功能,当出现多个通知,也无法统一关闭。
2 通知的配置
在通知实例上可以读取到设置通知时的所有配置,比如:
通知标题:instanceNotification. title、通知内容:instanceNotification. body、通知图标:instanceNotification. icon等。
注意: 这些属性都是只读的,不能删除,不能修改,不能遍历。
3 事件处理
通知实例具有四个事件钩子,来跟踪通知当前的状态。这些事件可以通过事件处理跟踪onshow、onclick、onclose和onerror。因为Notification同样继承自EventTarget,因此可以对它调用addEventListener()方法。我们可以使用通知的实例来监听通知的事件:
onclick: 用户点击通知时被触发
onshow: 通知显示的时候被触发
onerror: 通知遇到错误时被触发
onclose: 用户关闭通知时被触发
注意:最好是一发出通知就立即监听事件,否则有些事件可能一开始没被触发或永远不会触发。
例如:用定时器5秒后才监听通知的点击和显示事件,则永远不会触发通知显示的回调,点击事件在5秒后才可以正常起作用但会错误五秒之前用户的点击。

var instanceNotification = new Notification("您有一条订单消息,请及时处理!", { "icon": "", "body": "快点击处理吧!","requireInteraction":true }); instanceNotification.onshow = function () { console.log("显示通知"); //控制10s后再关闭 setTimeout(function () { n.close() }, 10000); }; instanceNotification.onclick = function () { alert("打开相关视图"); window.open("/note"); instanceNotification.close(); }; instanceNotification.onclose = function () { console.log("通知关闭"); }; instanceNotification.onerror = function () { console.log('错误'); };
六、完整示例demo

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>H5的Notification-Web的桌面通知功能</title> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js" type='text/javascript'></script> </head> <body> <div class="row"> <div class="col-md-12"> <button id="showNoti">点击通知</button> </div> </div> <script> var instanceNotification = Notification || window.Notification; console.log(instanceNotification); if (instanceNotification) { var permissionNow = instanceNotification.permission; if (permissionNow === 'granted') {//允许通知 creatNotification(); } else if (permissionNow === 'default') { setPermission(); } else if (permissionNow === 'denied') { console.log('用户拒绝了你!!!'); } else { setPermission(); } } function setPermission() { //请求获取通知权限 instanceNotification.requestPermission(function (PERMISSION) { if (PERMISSION === 'granted') { console.log('用户允许通知了!!!'); creatNotification(); } else { console.log('用户拒绝了你!!!'); } }); } function creatNotification() { if (!window.Notification) { alert("浏览器不支持通知!"); return false; } console.log(window.Notification.permission); if (window.Notification.permission != 'granted') { console.log('用户未开启通知权限!!!'); return false; } var instanceNotification = new Notification("您有一条订单消息,请及时处理!", { "icon": "", "body": "快点击处理吧!","requireInteraction":true }); instanceNotification.onshow = function () { console.log("显示通知"); //3s后自动关闭通知 setTimeout(function () { instanceNotification.close() }, 3*1000); }; instanceNotification.onclick = function () { alert("打开页面"); window.open("/note"); instanceNotification.close(); }; instanceNotification.onclose = function () { console.log("通知关闭"); }; instanceNotification.onerror = function () { console.log('错误'); }; } $(function () { $("#showNoti").click(function () { creatNotification(); }) }); //设置一个定时器,每隔5分钟进行一次通知 setInterval("creatNotification()",5*60*1000); </script> </body> </html>
七、遇到的问题
7.1.需要部署到服务器,且必须支持https
测试时,需要把html部署到服务器,通过域名进行访问,且需要支持https
7.2 浏览器的设置
一旦用户禁止网站显示通知,网站就不能再请求用户授权显示通知,需要用户去设置中更改。
chrome浏览器的通知设置位置:设置>高级>内容设置>通知>添加或修改
saafari浏览器:偏好设置>网站>通知>找到网站>修改权限/恢复默认
7.3 关闭请求权限
在chorme浏览器中:当用户关闭请求权限的弹窗(右上角的叉叉),页面还没刷新,我们可以再次向用户请求权限。页面刷新过后,浏览器默认用户拒绝。
在safari浏览器下,没有关闭请求权限的选项,用户必须选择同意/拒绝。
7.4 icon不显示问题
可能是网站进行了同源限制(比如github),不是域名下面的图片,会报错,不能调用。
7.5 tag
tag相同的通知,同时只能出现一个,老通知是否会被覆盖取决于:renotify配置和浏览器。
chrome下:当通知关闭之后,上次出现过的tag在一段时间内,不能再出现,比如刷新页面再请求相同tag的通知。(在safari下正常出现)
7.6 safari下面不能显示icon
在safari下面,同一个网站(比如谷歌),同样的代码,chorme可以正常显示icon,safari却没有icon,也没有报错。谷歌之后发现,在stack overflow里面看到safari只支持body和tag选项,并不支持icon选项。
7.7 连续触发
在safari和chrome下短时间内连续触发通知(不设tag,不设requireInteraction),会出现如下表现:
这个表现,通知没有icon、标题、内容,就显得没有意义了,浏览器以这种形式,限制开发者不要频繁打扰用户。
7.8 浏览器兼容性问题
截止到文章发布之前,目前测试谷歌、火狐、Microsoft Edge是没问题的
转载自joshua317博客 https://www.joshua317.com/article/49
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)