H5的Notification特性 - Web的桌面通知功能
本文为joshua317原创文章,转载请注明:转载自joshua317博客 https://www.joshua317.com/article/49
H5的Notification特性 - Web的桌面通知功能
关键词:HTML5中的Web Notification桌面通知;基于Web Notification的前端桌面弹窗;H5的Notification特性;Web的桌面通知功能;H5 notification浏览器桌面通知;HTML5 桌面通知:Notification API;html5新功能Notification;Notification桌面通知;windows桌面通知;浏览器桌面通知;
随着web的发展,功能越来越完善,今天聊一下h5的一个新特性--Notification。Notification API 是 HTML5 新增的桌面通知 API,用于向用户显示通知信息。该通知是脱离浏览器的,即使用户没有停留在当前标签页,甚至最小化了浏览器,该通知信息也一样会置顶显示出来,这样即使应用程序空闲或在后台也可以向用户发送信息。
一、问题背景
最近工作中客户反馈浏览器最小化后,不能及时收到消息,导致不能及时处理工作。经过调研发现可以使用web桌面通知来实现。即使用户最小化浏览器后,也可以通过通知及时的进行提。
二、引出
传统的桌面通知可以写一个div放到页面右下角自动弹出来,并通过轮询等等其他方式去获取消息并推送给用户。这种方式有个弊端就是:当我在使用京东 进行购物的时候,我是不知道人人网有消息推送过来给我的,而必须要等我把当前页面切到人人网才知道有消息推送了。这种方式的消息推送它是基于页面存活的, 但是我们需要这么一种策略:无论你在看哪个页面,只要有消息都应该能推送给我看到,这就是webkitNotification要解决的问题。 Notification生成的消息不依附于某个页面,仅仅依附于浏览器。
一个桌面通知生成的正常流程,我们先来看看一个桌面通知是如何生成的:
- 检查浏览器是否支持Notification
- 检查浏览器的通知权限(是否允许通知)
- 若权限不够则获取浏览器的通知权限
- 创建消息通知
- 展示消息通知
在调研过程中下,做了一个小demo,我用的是谷歌浏览器进行的测试。大致是这样子:
三、应用场景
Notifications
的诞生简化了网站或者应用与用户之间的沟通成本(时间成本和开发成本),增强用户黏性(减少了用户离开应用的可能)。传统的通知方式,大多是通过站内信(消息),邮件,短信等方式,它们通常需要刷新(跳转)页面、离开应用打开其他应用或终端来查看消息;而桌面通知功能大大的简化了这个过程,消息的传递基本不消耗时间(如果不设置setTimeout
,用时基本不会超过1s
),并且用户不需要离开应用,这都带来了极大的方便。可以预见,Notifications
将会在很多网页或应用中被大量使用。当然Notifications
也具有它的局限性:无法存档、即看即毁。有点类似我们使用智能机的时候,即使在后台运行,也能收到消息通知。 那么,这个功能到底能用在哪些场景呢?只能说能应用的场景很多:
- 电子商务网站
- 教育类网站
- 社交类网站
- 资讯类网站
- 网页版邮件服务
- 即时通讯软件(邮件、聊天室)
- 体育赛事结果彩票/抽奖结果
- 新闻网站重大新闻通知
- 网站的重大更新,重大新闻等。
- ...
举个例子,当你打开网站页面,你可能会看到(使用新版浏览器)如下图的通知:
四、特性
1.该通知是脱离浏览器的,即使用户没有停留在当前标签页,甚至最小化了浏览器,也会在主屏幕的右上角显示通知,然后在一段时间后消失。
2.我们可以监听通知的显示,点击,关闭等事件,比如点击通知打开一个页面。
五、介绍及用法
Notification 对象用来为用户设置和显示桌面通知,Web Notifications API 可以将通知发送至页面之外的系统层级上,因此,即便应用处于空闲状态或是在后台,web 应用仍然可以通过这个 API 向用户发送信息。比如访问博客时,每当用户收到一条新的消息,就会有一条通知显示给用户
用法
var notification = new Notification(title, [options])
参数
Param | Type | Description |
---|---|---|
title | string |
显示的通知标题 |
[options] | object |
显示通知的配置项,可选 |
[options.dir] | string |
文字方向, 取值为 auto、ltr、rtl 之一 |
[options.lang] | string |
通知的语言,这个字符串必须在 BCP 47 language tag 文档中是有效的。 |
[options.body] | string |
通知的内容 |
[options.tag] | string |
通知的 id,通过此 id 可以对通知进行刷新、替换或移除 |
[options.icon] | string |
通知的图标图片URL,将被用于显示通知的图标。 |
4.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('用户曾经拒绝授权,不能显示通知');
}
4.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('用户拒绝授权,不能显示通知');
}
});
4.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) // 显示通知
4.3.1 TITLE参数
TITLE
表示通知的标题。必须参数,允许数字、字符串和空
4.3.2 OPTIONS参数
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)
)时,会出现如下图的通知叠加状态。
这种情况显然,只能默认操作最后一个通知,除非你把每个通知返回的实例都保存下来。
注意:如果没有触发叠加,很可能是因为你两次通知的tag配置项是相同的(相同tag只能出现一个弹窗)。
注意: safari下不支持该选项,默认自动关闭
renotify:相同
默认值为false,chorme下相同tag的通知不替换,还是老的通知
设置为true
, 两个相同tag的通知,新通知替换之前旧的通知。
注意:使用renotify
,必须要同时设置tag
选项,否则将会报错。
PS: safari下不支持该选项,默认两个相同tag的通知,新通知替换之前旧的通知。
4.事件及事件钩子
生成通知,会返回一个实例,如下:
var instanceNotification = new Notification(title, options)
instanceNotification
就是当前通知的实例,在该实例上,我们可以查询该通知的配置,监听事件,调用实例方法。下文都以instanceNotification
指代通知返回的实例。
当通知被创建成功后:
-
1.通知实例具有一个静态方法可以用来关闭通知
-
2.读取相关的配置
-
3.通知实例具有四个事件钩子,来跟踪通知当前的状态。
4.4.1 关闭通知
instanceNotification.close()
没有设置不自动关闭的话,chrome通知将会在4.5秒左右自动关闭通知,safari则是5秒钟(无法设置不自动关闭)。
notification没有定时控制通知多久后消失的功能,当出现多个通知,也无法统一关闭。
4.4.2 通知的配置
在通知实例上可以读取到设置通知时的所有配置,比如:
通知标题:instanceNotification. title
、通知内容:instanceNotification. body
、通知图标:instanceNotification. icon
等。
注意: 这些属性都是只读的,不能删除,不能修改,不能遍历。
4.4.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
七、遇到的问题
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原创文章,转载请注明:转载自joshua317博客 https://www.joshua317.com/article/49
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~