web项目通知实现

给web加个酷炫的提醒吧

Posted by Li Yucang on September 11, 2017

web 项目通知实现

在一般的 web 项目中,通知可以说是比较常见的。私信、在线提问、或者一些在线即时通讯工具我们总是希望第一时间知道对方有了新的反馈,这个时候,就需要页面给予即使的通知。

传统的通知实现

在以前,我们的通知实现主要是修改页面的标题内容来实现,实现原理其实很简单,就是定时器不断修改 document.title 的值来产生视觉上的提示效果。

闪烁效果

setInterval(function() {
  if (document.title === '【新通知】') {
    document.title = '【   】';
  } else {
    document.title = '【新通知】';
  }
}, 500);

大家可以在任何的网页控制台输入以上代码,可以看到标题的闪烁效果。

文字移动效果

document.title = '您有新的未读消息!  ';
setInterval(() => {
  const title = document.title;
  document.title = title.substring(1, title.length) + title.charAt(0);
}, 200);

同样可以在控制台输入以上代码看看效果,这个看起来就跟横幅很像了。

h5 Notifications API

Notifications API 允许网页控制向最终用户显示系统通知 —这些都在顶级浏览上下文视口之外,因此即使用户已经切换标签页或移动到不同的应用程序,也可以显示。该 API 被设计成与不同平台上的现有通知系统兼容。

此特性一出,之前的修改 document.title 的做法就显得有点 low 了。不过需要注意的是,这个 api 目前只能在 https 协议下使用。so,如果你的网站还是 http 协议就快升级一下吧。

Notification 构造参数

let notification = new Notification(title, options)

通过 new 构造,显示通知。其中 title 是必须参数,表示通知小框框的标题内容。options 一个被允许用来设置通知的对象。它包含以下属性:

  • dir : 文字的方向;它的值可以是 auto(自动), ltr(从左到右), or rtl(从右到左)
  • lang: 指定通知中所使用的语言。这个字符串必须在 BCP 47 language tag 文档中是有效的。
  • body: 通知中额外显示的字符串。
  • tag: 赋予通知一个 ID,以便在必要的时候对通知进行刷新、替换或移除。
  • icon: 一个图片的 URL,将被用于显示通知的图标。

Notification.permission

一个用于表明当前通知显示授权状态的字符串。可能的值包括:denied (用户拒绝了通知的显示), granted (用户允许了通知的显示), 或 default (因为不知道用户的选择,所以浏览器的行为与 denied 时相同).

默认情况下,Notification.permission 的值是’default’。

Notification 方法

静态方法

Notification.requestPermission()

用于当前页面向用户申请显示通知的权限。这个方法只能被用户行为调用(比如:onclick 事件),并且不能被其他的方式调用。

最新的规范已将此方法更新为基于 promise 的语法,工作原理如下:

Notification.requestPermission().then(function(permission) { ... });

permission 字符串可以是 granted(被授予), denied(被拒绝) 或者 default(默认)。

以前,语法是基于一个简单的回调;此版本现已弃用:

Notification.requestPermission(callback);

实例方法

Notification.close()

用于关闭通知。

Notification 事件处理

  • Notification.onclick 处理 click 事件的处理。每当用户点击通知时被触发。
  • Notification.onshow 处理 show 事件的处理。当通知显示的时候被触发。
  • Notification.onerror 处理 error 事件的处理。每当通知遇到错误时被触发。
  • Notification.onclose 处理 close 事件的处理。当用户关闭通知时被触发。

实战

发出一条通知:

function notifyMe() {
  // 先检查浏览器是否支持
  if (!("Notification" in window)) {
    alert("This browser does not support desktop notification");
  }

  // 检查用户是否同意接受通知
  else if (Notification.permission === "granted") {
    // If it's okay let's create a notification
    var notification = new Notification("Hi there!");
  }

  // 否则我们需要向用户获取权限
  else if (Notification.permission !== 'denied') {
    Notification.requestPermission(function (permission) {
      // 如果用户同意,就可以向他们发送通知
      if (permission === "granted") {
        var notification = new Notification("Hi there!");
      }
    });
  }

  // 最后,如果执行到这里,说明用户已经拒绝对相关通知进行授权
  // 出于尊重,我们不应该再打扰他们了
}

在项目中,我们一般只在用户未在我们的 web 页面时触发通知。这里我们可以监听页面的失去焦点和获得焦点事件来判断是否开启通知。

window.onfocus = () => {
  show = false;
};
window.onblur = () => {
  show = true;
};
// IE
document.onfocusin = () => {
  show = false;
};
document.onfocusout = () => {
  show = true;
};

如果有其他逻辑需要监听这几个事件,就用 window.addEventListener 吧。

默认情况下,如果同时存在几条通知,会全部显示。我们可以为每条通知设置相同的 tag,然后把 renotify 设置为 true,这样当前标记的通知只会出现一个,后出现的会替换之前的:

new Notification(title, {
  tag: 'message',
  body: content,
  icon: image,
  renotify: true,
});

实际上,通知显示的时间大约有 20s。如果你觉得显示时间过长,可以提前将通知关闭:

const noticeObj = new Notification('hi');
noticeObj.onshow = () => {
  setTimeout(() => { noticeObj.close() }, 3000);
};

提醒

最后注意一下,由于这个 api 目前还未完全确定,未来存在变更的可能性,所有建议大家在使用时阅读最新的文档。