Notifications API 瀏覽器通知

通知 API

Notifications API允許我們向用戶顯示通知。 它非常強大且易於使用。在可能的情況下,它使用與原生應用程序相同的機制,提供完全原生的外觀和感覺。

我們可以將 Notifications API 分成兩個核心區域(這些是非技術性的,也不屬於規範的一部分)。調用 API (Invocation API) 控制如何使您的通知出現,包括樣式和振動。我們從頁面(或從服務器,在推送通知的情況下)創建(或調用)通知。交互 API 控制用戶與通知互動時發生的情況。 用戶交互在 service worker 中處理。

請求許可

在創建通知之前,我們需要獲得用戶的許可。放在主 JS 文件中

Notification.requestPermission(function (status) {
console.log("Notification permission status:", status);
});

顯示通知

可以使用showNotification方法(“調用 API”)顯示來自應用程序主腳本的通知 。這是一個例子:

function displayNotification() {
if (Notification.permission == "granted") {
navigator.serviceWorker.getRegistration().then(function (reg) {
reg.showNotification("Hello world!");
});
}
}

通知選項

showNotification方法有一個可選的第二個參數來配置通知。

function displayNotification() {
if (Notification.permission == "granted") {
navigator.serviceWorker.getRegistration().then(function (reg) {
var options = {
body: "Here is a notification body!",
icon: "images/example.png",
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: 1,
},
};
reg.showNotification("Hello world!", options);
});
}
}
  1. body選項將主要描述添加到通知中。為用戶提供足夠的信息來決定如何對其採取行動。

  2. icon選項附加圖像以使通知更具視覺吸引力,但也與用戶更相關。例如,如果是來自他們朋友的消息,您可能會包含發件人頭像的圖像。

  3. vibrate選項指定接收通知的電話的振動模式。在我們的示例中,手機會振動 100 毫秒,暫停 50 毫秒,然後再次振動 100 毫秒。

  4. data選項將自定義數據附加到通知,以便服務工作者可以在用戶與通知交互時檢索它。例如,向數據添加唯一的“id”“key”選項可以讓我們確定當服務工作者處理點擊事件時點擊了哪個通知。

測試通知選項網站

向通知添加操作

向用戶發送簡單通知,並在用戶點擊通知時,處理通知的基本互動,可以在通知中添加上下文,就可以讓使用者在不前往網站的情況下與網站互動。

function displayNotification() {
if (Notification.permission == "granted") {
navigator.serviceWorker.getRegistration().then(function (reg) {
var options = {
body: "Here is a notification body!",
icon: "images/example.png",
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: 1,
},
actions: [
{
action: "explore",
title: "Explore this new world",
icon: "images/checkmark.png",
},
{
action: "close",
title: "Close notification",
icon: "images/xmark.png",
},
],
};
reg.showNotification("Hello world!", options);
});
}
}

要使用一組自定義操作的按鈕,我們在通知選項物件中添加一個操作數組。這些物件定義要向用戶顯示的操作按鈕。

動作可以有一個標識符字符串,一個包含要向用戶顯示的文本的標題,以及一個包含要在動作旁邊顯示的圖像的位置的圖標。

監聽事件

現在我們需要在 service worker 中處理與通知互動(使用“Interaction API”)。用戶看到通知後,他們可以將其關閉或對其採取行動。

通知點擊事件

當用戶點擊通知時處理。點擊後會在service worker內部觸發一個notificationclick事件。

讓我們看一下在 service worker 中處理 click 事件的代碼。

self.addEventListener("notificationclick", function (e) {
var notification = e.notification;
var primaryKey = notification.data.primaryKey;
var action = e.action;

if (action === "close") {
notification.close();
} else {
clients.openWindow("http://www.example.com");
notification.close();
}
});

可以看到當通知的操作為close則關閉通知,否則開啟網頁

檢查權限

始終檢查使用通知 API 的權限。請務必檢查是否已授予權限,因為狀態可能會更改:

if (Notification.permission === "granted") {
/* do our magic */
} else if (Notification.permission === "blocked") {
/* the user has previously denied push. Can't reprompt. */
} else {
/* show a prompt to the user */
}

實作

利用 vscode LiveServe套件,建立即時更新的本機伺服器,不需再存檔後重整頁面來確認。

建立main.html

<!DOCTYPE html>
<html lang="en">
<head>
<script>
Notification.requestPermission(function (status) {
console.log("Notification permission status:", status);
registerServiceWorker();
});

function registerServiceWorker() {
if (!("serviceWorker" in navigator)) {
console.log("Service workers aren't supported in this browser.");
return;
}

navigator.serviceWorker
.register("/sw.js") // 註冊 service worker
.then(() => initialiseServiceWorker());
}

function initialiseServiceWorker() {
if (Notification.permission === "granted") {
/* do our magic */
displayNotification();
} else if (Notification.permission === "blocked") {
/* the user has previously denied push. Can't reprompt. */
console.log("用戶之前拒絕推送。 無法重新提示");
var info = document.querySelector(".info");
info.innerHTML = "您之前拒絕推送。 無法重新提示";
} else {
/* show a prompt to the user */
var info = document.querySelector(".info");
info.innerHTML = "請允許通知";
}
}

function displayNotification() {
if (Notification.permission == "granted") {
navigator.serviceWorker.getRegistration().then(function (reg) {
// reg記得在初始化之後,不然會是undefined
var options = {
body: "Here is a notification body!",
icon: "/notification.png",
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: 1,
},
actions: [
{
action: "explore",
title: "點擊前往新世界",
icon: "/share.png",
},
{
action: "close",
title: "關閉通知",
icon: "/close.png",
},
],
};
reg.showNotification("Hello world!", options);
});
}
}
</script>
</head>
<body>
<h1>Hello world!</h1>
<p>
<span class="info"></span>
<button onclick="displayNotification()">發送通知</button>
</p>
</body>
</html>

建立sw.js

self.addEventListener("install", (event) => {
console.log("Installed");
});

self.addEventListener("activate", (event) => {
console.log("Activated");
});

self.addEventListener("fetch", (event) => {
console.log("Fetch request");
});

self.addEventListener("notificationclick", function (e) {
var notification = e.notification;
var primaryKey = notification.data.primaryKey;
var action = e.action;
// 如果action是close關閉通知
if (action === "close") {
notification.close();
} else {
// 否的話開啟github,關閉通知
clients.openWindow("https://github.com/");
notification.close();
}
});

效果如下