前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >H5的Notification特性 - Web的桌面通知功能

H5的Notification特性 - Web的桌面通知功能

作者头像
joshua317
发布2021-08-31 18:00:01
2K0
发布2021-08-31 18:00:01
举报
文章被收录于专栏:技术博文技术博文

本文为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生成的消息不依附于某个页面,仅仅依附于浏览器。

一个桌面通知生成的正常流程,我们先来看看一个桌面通知是如何生成的:

  1. 检查浏览器是否支持Notification
  2. 检查浏览器的通知权限(是否允许通知)
  3. 若权限不够则获取浏览器的通知权限
  4. 创建消息通知
  5. 展示消息通知

在调研过程中下,做了一个小demo,我用的是谷歌浏览器进行的测试。大致是这样子:

三、应用场景

Notifications的诞生简化了网站或者应用与用户之间的沟通成本(时间成本和开发成本),增强用户黏性(减少了用户离开应用的可能)。传统的通知方式,大多是通过站内信(消息),邮件,短信等方式,它们通常需要刷新(跳转)页面、离开应用打开其他应用或终端来查看消息;而桌面通知功能大大的简化了这个过程,消息的传递基本不消耗时间(如果不设置setTimeout,用时基本不会超过1s),并且用户不需要离开应用,这都带来了极大的方便。可以预见,Notifications将会在很多网页或应用中被大量使用。当然Notifications也具有它的局限性:无法存档、即看即毁。有点类似我们使用智能机的时候,即使在后台运行,也能收到消息通知。 那么,这个功能到底能用在哪些场景呢?只能说能应用的场景很多:

  • 电子商务网站
  • 教育类网站
  • 社交类网站
  • 资讯类网站
  • 网页版邮件服务
  • 即时通讯软件(邮件、聊天室)
  • 体育赛事结果彩票/抽奖结果
  • 新闻网站重大新闻通知
  • 网站的重大更新,重大新闻等。
  • ...

举个例子,当你打开网站页面,你可能会看到(使用新版浏览器)如下图的通知:

四、特性

1.该通知是脱离浏览器的,即使用户没有停留在当前标签页,甚至最小化了浏览器,也会在主屏幕的右上角显示通知,然后在一段时间后消失。

2.我们可以监听通知的显示,点击,关闭等事件,比如点击通知打开一个页面。

五、介绍及用法

Notification 对象用来为用户设置和显示桌面通知,Web Notifications API 可以将通知发送至页面之外的系统层级上,因此,即便应用处于空闲状态或是在后台,web 应用仍然可以通过这个 API 向用户发送信息。比如访问博客时,每当用户收到一条新的消息,就会有一条通知显示给用户

用法

代码语言:javascript
复制
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才会显示通知消息

代码语言:javascript
复制
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)是请求获取权限的方法(有点类似javascriptconfirm弹窗窗),允许传入一个回调,回调会返回用户选择的何种权限,返回两个值,granted代表允许,denied代表拒绝。并且Notification.requestPermission()支持then方式的链式调用,也就意味着可以异步调用它。

Notification.permissiondefault的时候,我们需要使用Notification.requestPermission()来请求用户权限。

Notification.requestPermission()基于promise语法,then的回调函数参数是用户权限的状态Notification.permission的值。

代码语言:javascript
复制
//方式一,老版是回调函数机制
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.permissiongranted时,请求到用户权限之后,不必立即发送通知,可以在任意时刻,以任意形式来发送通知。new Notification(TITLE, OPTIONS)方法创建可以创建一个通知实例,允许参入参数两个参数TITLEOPTIONS。注意默认情况下(实际可以通过OPTIONS中的timestamp参数控制)一旦通知实例被创建出来,它会立即被显示出来

代码语言:javascript
复制
var options = {}; // 传空配置
var title = '消息标题';
var notification = new Notification(title, options) // 显示通知
4.3.1 TITLE参数

TITLE表示通知的标题。必须参数,允许数字、字符串和空

4.3.2 OPTIONS参数

OPTIONS是非必须参数,必须为一个对象,它包含: ps: 部分参数在某些浏览器可能会不生效,建议使用最新版的谷歌浏览器。以下某些内容从Notification-MDN-EN结合谷歌翻译得来,很有可能翻译不准确,如有,请提出。

代码语言:javascript
复制
{
    //通知显示正文。非必须,默认为空
    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.事件及事件钩子

生成通知,会返回一个实例,如下:

代码语言:javascript
复制
var instanceNotification = new Notification(title, options)

instanceNotification就是当前通知的实例,在该实例上,我们可以查询该通知的配置,监听事件,调用实例方法。下文都以instanceNotification指代通知返回的实例。

当通知被创建成功后:

  • 1.通知实例具有一个静态方法可以用来关闭通知
  • 2.读取相关的配置
  • 3.通知实例具有四个事件钩子,来跟踪通知当前的状态。
4.4.1 关闭通知
代码语言:javascript
复制
instanceNotification.close()

没有设置不自动关闭的话,chrome通知将会在4.5秒左右自动关闭通知,safari则是5秒钟(无法设置不自动关闭)。

notification没有定时控制通知多久后消失的功能,当出现多个通知,也无法统一关闭。

4.4.2 通知的配置

在通知实例上可以读取到设置通知时的所有配置,比如:

通知标题:instanceNotification. title、通知内容:instanceNotification. body、通知图标:instanceNotification. icon等。

注意: 这些属性都是只读的,不能删除,不能修改,不能遍历。

4.4.3 事件处理

通知实例具有四个事件钩子,来跟踪通知当前的状态。这些事件可以通过事件处理跟踪onshowonclickoncloseonerror。因为Notification同样继承自EventTarget,因此可以对它调用addEventListener()方法。我们可以使用通知的实例来监听通知的事件:

  • onclick: 用户点击通知时被触发
  • onshow: 通知显示的时候被触发
  • onerror: 通知遇到错误时被触发
  • onclose: 用户关闭通知时被触发

注意:最好是一发出通知就立即监听事件,否则有些事件可能一开始没被触发或永远不会触发。

例如:用定时器5秒后才监听通知的点击和显示事件,则永远不会触发通知显示的回调,点击事件在5秒后才可以正常起作用但会错误五秒之前用户的点击。

代码语言:javascript
复制
       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

代码语言:javascript
复制
<!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>

HTML

Copy

七、遇到的问题

7.1.需要部署到服务器,且必须支持https

测试时,需要把html部署到服务器,通过域名进行访问,且需要支持https

7.2 浏览器的设置

一旦用户禁止网站显示通知,网站就不能再请求用户授权显示通知,需要用户去设置中更改。

chrome浏览器的通知设置位置:设置>高级>内容设置>通知>添加或修改

saafari浏览器:偏好设置>网站>通知>找到网站>修改权限/恢复默认

7.3 关闭请求权限

在chorme浏览器中:当用户关闭请求权限的弹窗(右上角的叉叉),页面还没刷新,我们可以再次向用户请求权限。页面刷新过后,浏览器默认用户拒绝。

在safari浏览器下,没有关闭请求权限的选项,用户必须选择同意/拒绝。

7.4 icon不显示问题

可能是网站进行了同源限制(比如github),不是域名下面的图片,会报错,不能调用。

7.5 tag

  1. tag相同的通知,同时只能出现一个,老通知是否会被覆盖取决于:renotify配置和浏览器。
  2. 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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-08-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • H5的Notification特性 - Web的桌面通知功能
    • 一、问题背景
      • 二、引出
        • 三、应用场景
          • 四、特性
            • 4.1 通知权限 - Notification.permission
            • 4.2 请求权限 - Notification.requestPermission(CALLBACK)
            • 4.3 创建通知 - new Notification(TITLE, OPTIONS)
            • 4.事件及事件钩子
          • 六、完整示例demo
            • 七、遇到的问题
              • 7.1.需要部署到服务器,且必须支持https
              • 7.2 浏览器的设置
              • 7.3 关闭请求权限
              • 7.4 icon不显示问题
              • 7.5 tag
              • 7.6 safari下面不能显示icon
              • 7.7 连续触发
              • 7.8 浏览器兼容性问题
          相关产品与服务
          短信
          腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档