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

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

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('用户曾经拒绝授权,不能显示通知');
}
View Code
复制代码

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('用户拒绝授权,不能显示通知');
      }
});
View Code
复制代码

 

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) // 显示通知
View Code

   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
}
View Code
复制代码

其中,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('错误');
        };
View Code
复制代码

六、完整示例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>
View Code
复制代码

七、遇到的问题

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

 

posted @   Deer-Mr  阅读(731)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示