那些被忽略但很好用的 Web API / Notification

订阅、分享、开启小铃铛,才不会错过通知喔~

各位有没有收过网站的通知呢?例如 Youtube 或 Netflix 的新片通知,或是 Facebook 的讯息通知等等...,这个其实就是今天要介绍的 Notification 所达成的效果。


Notification

不过实话是,真的要像 Youtube 那样在使用者没有拜访网站的状况下发送通知,是需要使用 Service Worker 以及後端的配合,有兴趣的人可以看看 这篇文章,有详细说明如何推送未拜访网站情况下的通知,而今天我们的范畴就先聚焦在如何在「浏览情况下」发送通知吧。

https://ithelp.ithome.com.tw/upload/images/20211013/20125431awp5zFYorX.png

Notification 对於电脑浏览器到支援度是不错的,但在行动装置上就很糟糕了,iOS 全军覆没,Android 也是有使用上的限制,所以使用上还是需要注意一下的。

 

# Window.Notification

Notification 使用起来并不困难,它本身是一个建构函式,透过 new 关键字创建,并传入一个必要参数即可:

// 检查浏览器是否有支援 Notification
if ("Notification" in window) {
  let notification = new Notification("这是一则通知");
}

Notification 的第一个参数是 title,会显示为通知的标题,该参数为必传参数,而除了 title 之外,你也可以传入一个可选参数 options,它为一个物件,当中有更多关於通知的详细设定,下面我只列出几个我认为比较实用的,若对其他属性有兴趣的话可以看 这里

  • body: 一组字串,会设定为通知的内文,位置会在 title 的下方。
  • image: 一组图片的 URL 字串,它会成为通知的主视觉图片。
  • icon: 一组图片的 URL 字串,它会成为通知的图标,位置大小依系统原生通知而定。
  • data: 任意的资料格式,任何与通知相关的资料可以放在这,不会显示在通知当中,一般情境下比较少用,
  • requireInteraction: 一个布林值,决定通知必须要由使用者来关闭,而不是使其自动关闭,预设值为 false

注意: 每个作业系统对於不同的设定属性有不同的支援或做法,最终的行为可能不会相同,例如 macOS 不支援 image 图片显示。

<button onclick="notifyMe()">click</button>
<script>
  function notifyMe() {
    let notification = new Notification("这里是通知的标题", {
      body: "这里是通知的内文",
      icon: "./max.jpg",
      image: "./max.jpg",
      requireInteraction: true,
    });
  }
</script>

https://ithelp.ithome.com.tw/upload/images/20211013/20125431oPcXuxZJNJ.png

可以看到不同作业系统本身在通知的显示上有很大的不同,而且针对同一个属性也会有不同的行为模式:

  • 首先在 macOS 上,右边的图示是根据 icon 的设定显示的,而非 image,但 Microsoft 就同时显示了 iconimage
  • 再者,由於设定了 requireInteraction,所以当使用者没有主动关闭中前 macOS 会将通知讯息叠加显示,反之 Microsoft 并不会,要等到第一条通知被关闭後,第二条才会出现。

 

# Notification 实体

如果我们在创建 Notification 时有将宣告在变数中,我们就可以取得 Notification 实体,并访问它的相关属性,而它的属性其实就是当初在呼叫建构函式时所传入的参数,像是这样:

let notification = new Notification("这是一则通知", {
  body: "这是 Max 的通知",
  icon: "./max.jpg",
  data: { name: "Max" },
  requireInteraction: true,
});

console.log(notification.title); // "这是一则通知"
console.log(notification.body); // "这是 Max 的通知"
console.log(notification.data.name); // "Max"
console.log(notification.requireInteraction); // true

另外除了这些唯读属性外,我们还可以为通知绑定事件,而且事件的 Callback 也和其他事件一样,可以接到一个 Event 物件,当中的 event.target 就会是被触发事件的 Notification 实体。

可监听的事件有:

  • click: 使用者点击通知时触发,关闭时的点击不包含在内。
  • error: 当通知发生错误时触发。
let notification = new Notification("这是一则通知", {
  body: "这是 Max 的通知",
  icon: "./max.jpg",
  data: { name: "Max" },
  requireInteraction: true,
});

notification.addEventListener("click", function (event) {
  console.log(event.target.data.name); // "Max"

  // 打开页面是一个常见的点击事件行为
  window.open("https://maxleebk.com/", "_blank");
});

 

# Window.Notification.permission

由於 Notification 算是一个有点打扰使用者的功能,所以使用前是需要取得授权的,而 Notification 这个建构函示(class)本身有提供 permission 这个静态属性让我们确认授权的状态。

当我们访问 permission 时会读取到一个表示授权状态的字串,其值可能会是以下三种:

  • "granted": 表示使用者允许网站的通知功能。
  • "denied": 表示使用者阻挡网站的通知功能,直到使用者主动到浏览器设定中开启通知。
  • "default": 表示使用者对於通知功能还没有明确的授权与否。
if (!window.Notification) {
  console.log("这个浏览器不支援 Notification");
} else if (Notification.permission === "granted") {
  let notification = new Notification("这是一则通知");
} else if (Notification.permission === "denied") {
  alert("建议您允许通知,以收到最新消息");
}

 

# Window.Notification.requestPermission

若是授权状态为 "default",那表示使用者并未对通知功能表示明确的答覆,这时候就需要我们使用 requestPermission 来询问,它本身会再去确认一次授权状态,若发现状态为 "default" 就会跳出询问授权的对话框,并且在使用者答覆之後利用 Promise 将结果丢给我们。

if (!window.Notification) {
  console.log("这个浏览器不支援 Notification");
} else if (Notification.permission === "granted") {
  let notification = new Notification("这是一则通知");
} else if (Notification.permission === "denied") {
  alert("建议您允许通知,以收到最新消息");
} else if (Notification.permission === "default") {
  Notification.requestPermission().then((result) => {
    // result 相当於 Notification.permission
    if (result === "granted") {
      let notification = new Notification("这是一则通知");
    }
  });
}

https://ithelp.ithome.com.tw/upload/images/20211013/201254316tfx5RmrGV.png

前面有说,其实 requestPermission 会自己再去确认一次状态,如果为 "default" 才会询问使用者,反之则会直接将授权状态丢给我们,所以我们其实直接呼叫它就好,不一定要先透过 permission 来判断。

Notification.requestPermission().then((result) => {
  if (result === "granted") {
    let notification = new Notification("这是一则通知");
  } else if (result === "denied") {
    alert("建议您允许通知,以收到最新消息");
  }
});

 

以上就是 Notification API 的大致内容了,但就如开头所说,其实它还是搭配 Service Worker 才会有更强大的效果,尤其是网站有提供订阅服务的话,那它的帮助绝对是非常大的,不过至少今天我们已经知道如何发送通知了,未来如果有机会和後端配合也可以快速上手。


<<:  30天打造品牌特色电商网站 Day.28 网站分析工具

>>:  创建App-上传App

【LeetCode】Array

本文会提到做 array 常犯错误、如何避免,与常见的技巧。 此系列 Leetcode 篇不介绍基本...

鞋业的制作与知识的应用

任何一项产品和工程的完成,除非是企业够大,能够独立用母子公司运作完成,否则以一般规模的中小企业体,产...

运算与表达

算数运算符 + - * / % // 以上都是常用的算术运算符 举个例子 python = 5 c ...

[DAY08] 部署用 Designer 做好的 Pipiline 到 Web API

DAY08 部署用 Designer 做好的 Pipeline 到 Web API 昨天我们用 De...

Android x Kotlin : EditText与软键盘常见设定

简介 editText有些常用设定,有时候会不小心忽略掉。虽然有些不是必备,但使用者体验的优化还是很...