文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

这篇文章由 Julian Motz 同行评审。 感谢所有 SitePoint 的同行评审,使 SitePoint 的内容成为最好的!

我们生活在一个你喜爱的网站或应用程序的通知不再仅仅存在于智能手机范围内的世界里。 现在,更常见的是直接通过浏览器接收通知。 例如,如果你有人请求添加你为好友或有人对提到你的故事发表评论时,Facebook会向你发送通知。 Slack是一个受欢迎的聊天应用程序,当你在对话中被提及时会向你发送通知。

第 1 段(可获 1.28 积分)

作为一个前端开发人员,我很好奇如何利用浏览器中的网站进行通知而不用处理大流量的信息。 如何根据访问者对我网站的兴趣,添加与访问者相关的浏览器通知?

在本文中,我们将在 Concise CSS website上实现一个通知系统,在每次框架有新版本发布时提醒访问者。 接下来我会告诉你我是如何通过使用浏览器 Notification API 中的 localStorage 来实现这一点的。

A browser notification displaying on the concisecss.com website, using the Notification API

Notification API的基本知识

首先,我们需要确定访问者的web浏览器是否支持通知。 在整个教程中,这个首要任务由 notification object 完成。

第 2 段(可获 1.56 积分)
(function() {
  if ("Notification" in window) {

  }
})();

到目前为止,我们只能确定我们的访问者的浏览器是否支持通知。 确定之后,我们需要知道我们是否可以向访问者显示权限。

我们将 permission property 的输出存储在一个变量中。 如果权限被授予或拒绝,什么也不返回。 如果以前没有请求权限,我们使用 requestPermission方法。

(function() {
  if ("Notification" in window) {
    var permission = Notification.permission;

    if (permission === "denied" || permission === "granted") {
      return;
    }

    Notification.requestPermission();
  }
})();
第 3 段(可获 0.81 积分)

Popup letting the user to allow or block browser notifications

在Web浏览器中你应该看到过类似于上图的通知。

现在我们已经请求到权限,让我们修改代码,以便在允许的情况下显示通知:

(function() {
  if ("Notification" in window) {
    var permission = Notification.permission;

    if (permission === "denied" || permission === "granted") {
      return;
    }

    Notification
      .requestPermission()
      .then(function() {
        var notification = new Notification("Hello, world!");
      });
  }
})();

JavaScript notification example

虽然无趣,但功能实现了。

这里我们使用 requestPermission() 方法中基于许可的语法在被授予权限后显示通知。 使用 notification constructor 函数来显示通知。 构造函数需要两个参数,一个用于通知的标题,另一个用于选项。 按照文档的链接可以找到能被传递的选项的完整列表。

第 4 段(可获 1.18 积分)

保存框架版本

在本文前面的内容中,我提到使用 localStorage 来帮助我们显示通知。 使用localStorage是在JavaScript 中存储持久性客户端信息的首选方法。 我们创建一个名为conciseVersion 的 localStorage 键,它将包含框架的当前版本(例如1.0.0)。 然后我们可以使用这个键来检查框架的新版本。

如何使用最新版本的框架更新 conciseVersion 键的值? 每当有人访问网站时,我们需要一种设置当前版本的方法。此外, 我们还需要在发布新版本时更新该值。 每次 conciseVersion 值更改时,我们向访问者显示一个通知,宣布该框架有新的版本。

第 5 段(可获 1.66 积分)

我们通过向页面中添加一个隐藏元素来解决这个问题。 这个元素有一个名为 js-currentVersion 的类,并且只包含框架的当前版本。 因为这个元素存在于DOM中,所以我们可以使用 JavaScript 轻松地与它进行交互。

这个隐藏元素将用于在 conciseVersion 键中存储框架版本。 当发布新版本的框架时,我们还可以使用此元素来更新该键。

<span class="js-currentVersion" aria-hidden="true">3.4.0</span>

我们可以使用一点CSS样式来隐藏这个元素:

第 6 段(可获 1.15 积分)
[aria-hidden="true"] {
  display: none;
  visibility: hidden;
}

注意:由于此元素没有实际内容,屏幕不必访问此元素。 这就是为什么我将 aria-hidden 属性设置为true,并使用display: none 作为隐藏元素方法的原因。想获取有关隐藏内容的更多信息,请参阅 WebAIM article

现在我们可以接收这个元素并在 JavaScript 中与它交互。 我们需要写一个函数,这个函数返回刚刚创建的隐藏元素里面的文本。

function checkVersion() {
  var latestVersion = document.querySelector(".js-currentVersion").textContent;
}
第 7 段(可获 1 积分)

此函数通过使用 textContent属性来存储.js-currentVersion 元素的内容。 让我们添加另一个变量来保存 conciseVersionlocalStorage 键的内容。

function checkVersion() {
  var latestVersion = document.querySelector(".js-currentVersion").textContent;
  var currentVersion = localStorage.getItem("conciseVersion");
}

现在我们有一个保存最新版本的框架的变量,将 localStorage键保存到变量中。 现在开始添加确定是否有可用的新版本框架的逻辑。

第 8 段(可获 0.83 积分)

我们首先检查 conciseVersion 键是否存在。 如果没有,我们向用户显示通知,因为这可能是他们第一次访问。 如果存在,我们检查它的值(保存在currentVersion变量中)是否大于当前版本(保存在latestVersion变量中)的值。 如果最新的框架版本大于访问者最后看到的版本,我们知道已经发布了一个新版本。

知道这一点,我们向访问者显示一个通知,同时相应地更新 conciseVersion 键。

function checkVersion() {
  var latestVersion = document.querySelector(".js-currentVersion").textContent;
  var currentVersion = localStorage.getItem("conciseVersion");

  if (currentVersion === null || currentVersion < latestVersion ) {      
    var notification = new Notification("Hello, world!");

    localStorage.setItem("conciseVersion", latestVersion);
  }
}

要使用此功能,我们需要修改下面的权限代码。

(function() {
  if ("Notification" in window) {
    var permission = Notification.permission;

    if (permission === "denied") {
      return;
    } else if (permission === "granted") {
      return checkVersion();
    }

    Notification.requestPermission().then(function() {
      checkVersion();
    });
  }
})();
第 9 段(可获 1.34 积分)

这允许我们在用户先前已授予权限或刚刚授予权限时显示通知。

显示通知

到目前为止,我们只向用户显示了不包含太多信息的简单通知。 接下来编写一个允许我们即时创建浏览器通知的函数,同时控制通知不同方面的内容。

函数具有正文文本,图标,标题,可选链接以及通知持续时间等参数。 在函数里面,我们创建一个选项对象,用来保存通知的正文文本和图标。还需要创建一个 Notification  对象的新实例,用来传递通知的标题以及选项对象。

第 10 段(可获 1.48 积分)

接下来,如果要链接到通知,需要添加一个 onclick 事件处理程序。 我们使用 setTimeout() 函数在指定的时间后关闭通知。 如果在调用此函数时没有指定时间,则使用默认值5秒。

function displayNotification(body, icon, title, link, duration) {
  link = link || null; // Link is optional
  duration = duration || 5000; // Default duration is 5 seconds

  var options = {
    body: body,
    icon: icon
  };

  var n = new Notification(title, options);

  if (link) {
    n.onclick = function () {
      window.open(link);
    };
  }

  setTimeout(n.close.bind(n), duration);
}

现在,我们修改 checkVersion() 函数来向用户显示一条信息更丰富的通知。

function checkVersion() {
  var latestVersion = document.querySelector(".js-currentVersion").textContent;
  var currentVersion = localStorage.getItem("conciseVersion");

  if (currentVersion === null || currentVersion < latestVersion ) {      
    displayNotification(
      `Click to see what's new in v${latestVersion}`,
      "http://concisecss.com/images/logo.png",
      "A new version of Concise is available",
      `https://github.com/ConciseCSS/concise.css/releases/v${latestVersion}`
    );

    localStorage.setItem("conciseVersion", latestVersion);
  }
}

我们使用 displayNotification 函数为我们的通知添加描述,图片,标题和链接。

注意:我们使用 ES6 的 template literals 在我们的文本中嵌入表达式。

第 11 段(可获 1.03 积分)

代码完成开始测试

下面你可以看到我们在教程中写过的完整代码。

请参阅CodePen 上由Keenan Payne(@keenanpayne)发表的 Implementing Dynamic Browser Notifications 。

 

运行上述代码在浏览器中应该生成以下通知。

Final notification example

谈到测试,你需要了解浏览器的通知权限。 有一些在 Google ChromeSafariFireFox 和 Microsoft Edge 等浏览器中管理通知的标准可以借鉴。 此外,你应该熟练使用控制台删除和修改 localStorage 值以便于测试。

你可以通过更改 js-currentVersion HTML元素的值运行一次脚本来测试教程中的例子,这样可以看到差异所在。 也可以使用相同的版本重新运行,以确认你不会收到不必要的通知。

第 12 段(可获 1.66 积分)

进一步

这就是我们需要的动态浏览器通知! 如果你希望你的浏览器通知更加灵活,我建议你学习一下 Service Worker API。 Service workers 可以用来对 push notifications 作出反应,无论用户是否正在访问你的网站,都可以收到通知,从而更及时地更新版本。

如果你有任何问题,意见或反馈,请随时在下面评论。 我也希望看到将 JavaScript 通知合并到你的项目中的例子。

第 13 段(可获 1.25 积分)

文章评论